Пример #1
0
        private void BoxTypeImpl(Dictionary <InterType, string> BoxTypes, InterType type, object tag)
        {
            if (type.IsNullable)
            {
                InterType instant = type.GenericArguments[0].Type;

                string labelsSufix   = rnd.Next().ToString();
                string hasValueLabel = "hasValue" + labelsSufix;
                string exitLabel     = "exit" + labelsSufix;

                MethodRef hasValueMethodRef = new MethodRef(namesController.TypeNameToJava(type),
                                                            ClassNames.SystemNullable_1.GetHasValueMethodName, "()Z");
                MethodRef valueMethodRef = new MethodRef(hasValueMethodRef.Class,
                                                         ClassNames.SystemNullable_1.GetValueMethodName, "()" + namesController.GetFieldDescriptor(instant));

                codeGenerator
                .Add(OpCodes.dup, null, tag)
                .Add(OpCodes.invokevirtual, hasValueMethodRef, tag)
                .Add(OpCodes.ifne, hasValueLabel, tag)
                .Add(OpCodes.pop, null, tag)
                .Add(OpCodes.aconst_null, null, tag)
                .Add(OpCodes._goto, exitLabel, tag)
                .Label(hasValueLabel)
                .Add(OpCodes.invokevirtual, valueMethodRef, tag);

                BoxType(instant, tag);

                codeGenerator.Label(exitLabel);
                return;
            }

            if (type.IsEnum)
            {
                codeGenerator.Add(Java.OpCodes.invokestatic, new Java.Constants.MethodRef(
                                      namesController.TypeNameToJava(type), ClassNames.EnumGetBoxedMethodName,
                                      "(" + namesController.GetFieldDescriptor(type.ElementType) + ")L" +
                                      namesController.TypeNameToJava(type.Fullname) + ";"));
                return;
            }

            if (type.IsValueType)
            {
                return;
            }

            if (!BoxTypes.ContainsKey(type))
            {
                Messages.Message(MessageCode.UnknownPrimitiveType, type.ToString());
                type = InterType.PrimitiveTypes[(int)PrimitiveType.Int32];
            }

            string boxType = BoxTypes[type];

            Java.Constants.MethodRef valueOfRef = new Java.Constants.MethodRef(
                namesController.TypeNameToJava(boxType),
                "valueOf",
                "(" + namesController.GetFieldDescriptor(type) + ")L" + namesController.TypeNameToJava(boxType) + ";");
            codeGenerator.Add(Java.OpCodes.invokestatic, valueOfRef, tag);
        }
Пример #2
0
        private void CompileAddressOf(ILExpression e, ExpectType expectType)
        {
            e = e.Arguments[0];

            if (e.Operand is TypeReference)
            {
                //ValueType
                CompileExpression(e, expectType);
                return;
            }
            else if (!(e.Operand is MethodReference))
            {
                CompileExpression(e, ExpectType.Boxed);
                return;
            }

            InterMethod method  = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments);
            InterType   operand = method.DeclaringType;

            if (!operand.IsArray)
            {
                //Getter
                if (method.ReturnParameter.Type.IsPrimitive)
                {
                    CompileExpression(e, ExpectType.Boxed);
                }
                else
                {
                    CompileExpression(e, GetExpectType(method.ReturnParameter));
                }
                return;
            }

            JavaArrayType arrType = JavaHelpers.InterTypeToJavaArrayType(operand);

            string arrayByRefName = byRefController.GetArrayByRefTypeName(operand);

            Java.Constants.Class arrayByRefNameClass =
                new Java.Constants.Class(namesController.TypeNameToJava(arrayByRefName));
            Java.Constants.MethodRef arrayByRefInitMethodRef =
                byRefController.GetArrayByRefCtorMethodRef(operand);

            codeGenerator
            .Add(OpCodes._new, arrayByRefNameClass, e)
            .Add(OpCodes.dup, null, e);

            CompileExpression(e.Arguments[0], ExpectType.Reference);    //array
            CompileExpression(e.Arguments[1], ExpectType.Primitive);    //first index

            for (int i = 0; i < operand.ArrayRank - 1; i++)
            {
                codeGenerator.Add(Java.OpCodes.aaload, null, e);
                CompileExpression(e.Arguments[i + 2], ExpectType.Primitive);
            }

            codeGenerator.Add(OpCodes.invokespecial, arrayByRefInitMethodRef, e);
        }
Пример #3
0
        private void CompileLdloca(ILExpression e, ExpectType expectType)
        {
            ILVariable operand     = (ILVariable)e.Operand;
            int        varIndex    = GetVarIndex(operand);
            InterType  operandType = resolver.Resolve(operand.Type, thisMethod.FullGenericArguments);

            if (operandType.IsValueType)
            {
                codeGenerator.AddLoad(JavaPrimitiveType.Ref, varIndex);
                return;
            }

            if ((operandType.IsPrimitive) && (expectType == ExpectType.Reference))
            {
                codeGenerator.AddLoad(JavaHelpers.InterTypeToJavaPrimitive(operandType), varIndex, e);
                TranslateType(operandType, ExpectType.Boxed, e);
                return;
            }

            string localByRefName = byRefController.GetLocalByRefTypeName(operandType);

            Java.Constants.Class localByRefNameClass =
                new Java.Constants.Class(namesController.TypeNameToJava(localByRefName));
            Java.Constants.MethodRef localByRefInitMethodRef =
                byRefController.GetLocalByRefCtorMethodRef(operandType);
            Java.Constants.MethodRef getValueMethodRef =
                byRefController.GetByRefGetValueMethodRef(JavaHelpers.InterTypeToJavaPrimitive(operandType));

            int localRefTempVar = GetNextFreeVar(JavaPrimitiveType.Ref);

            codeGenerator
            .Add(OpCodes._new, localByRefNameClass, e)
            .Add(OpCodes.dup, null, e)
            .AddLocalVarInstruction(LocalVarInstruction.Load, JavaHelpers.InterTypeToJavaPrimitive(operandType), varIndex, e)
            .Add(OpCodes.invokespecial, localByRefInitMethodRef, e)
            .Add(OpCodes.dup, null, e)
            .AddLocalVarInstruction(LocalVarInstruction.Store, JavaPrimitiveType.Ref, localRefTempVar, e);

            RegisterLocalByRef(() =>
            {
                codeGenerator
                .AddLocalVarInstruction(LocalVarInstruction.Load, JavaPrimitiveType.Ref, localRefTempVar, e)
                .Add(OpCodes.invokevirtual, getValueMethodRef, e);

                if ((!operandType.IsPrimitive) && (!operandType.IsEnum))
                {
                    codeGenerator.Add(OpCodes.checkcast,
                                      new Java.Constants.Class(namesController.TypeNameToJava(operandType)), e);
                }

                codeGenerator.AddLocalVarInstruction(LocalVarInstruction.Store, JavaHelpers.InterTypeToJavaPrimitive(operandType), varIndex, e);

                FreeVar(localRefTempVar, JavaPrimitiveType.Ref);
            });

            //TODO: TranslateType if neeeded
        }
Пример #4
0
        private void CompileUnbox_Any(ILExpression e, ExpectType expect)
        {
            InterType operand      = resolver.Resolve((TypeReference)e.Operand, thisMethod.FullGenericArguments);
            InterType nullableType = null;

            if (operand.IsNullable)
            {
                nullableType = operand;
                operand      = operand.GenericArguments[0].Type;

                codeGenerator
                .Add(OpCodes._new, new Java.Constants.Class(namesController.TypeNameToJava(nullableType)), e)
                .Add(OpCodes.dup, null, e);
            }

            CompileExpression(e.Arguments[0], ExpectType.Boxed);

            string boxType = GetBoxType(operand);

            Java.Constants.Class operandRef = new Java.Constants.Class(namesController.TypeNameToJava(boxType));

            Java.Constants.MethodRef valueRef;

            if (operand.IsValueType)
            {
                valueRef = new Java.Constants.MethodRef(operandRef.Value, ClassNames.ValueTypeGetCopy, "()" +
                                                        namesController.GetFieldDescriptor(operand));
            }
            else if (operand.IsEnum)
            {
                valueRef = new MethodRef(operandRef.Value, ClassNames.EnumGetUnboxedMethodName,
                                         "()" + namesController.GetFieldDescriptor(operand.ElementType));
            }
            else
            {
                valueRef = new Java.Constants.MethodRef(operandRef.Value,
                                                        Utils.GetJavaTypeName(operand.PrimitiveType) + "Value",
                                                        "()" + namesController.GetFieldDescriptor(operand));
            }

            codeGenerator
            .Add(Java.OpCodes.checkcast, operandRef, e)
            .Add(Java.OpCodes.invokevirtual, valueRef, e);

            if (nullableType != null)
            {
                codeGenerator.Add(OpCodes.invokespecial, new MethodRef(
                                      namesController.TypeNameToJava(nullableType),
                                      ClassNames.JavaConstructorMethodName,
                                      "(" + namesController.GetFieldDescriptor(operand) + ")V"));
            }
        }
Пример #5
0
        private void CompileLdelema(ILExpression e, ExpectType expectType)
        {
            TypeReference typeRef = e.Operand as TypeReference;
            InterType     operand = resolver.Resolve(typeRef, thisMethod.FullGenericArguments);
            JavaArrayType arrType = JavaHelpers.InterTypeToJavaArrayType(operand);

            if (operand.IsValueType)
            {
                CompileExpression(e.Arguments[0], ExpectType.Reference);    //array
                CompileExpression(e.Arguments[1], ExpectType.Primitive);    //index

                codeGenerator.Add(OpCodes.aaload, null, e);
                return;
            }

            if ((operand.IsPrimitive) && (expectType == ExpectType.Reference))
            {
                CompileExpression(e.Arguments[0], ExpectType.Reference);    //array
                CompileExpression(e.Arguments[1], ExpectType.Primitive);    //index

                codeGenerator.AddArrayLoad(arrType);
                TranslateType(operand, ExpectType.Boxed, e);
                return;
            }

            string arrayByRefName = byRefController.GetArrayByRefTypeName(operand);

            Java.Constants.Class arrayByRefNameClass =
                new Java.Constants.Class(namesController.TypeNameToJava(arrayByRefName));
            Java.Constants.MethodRef arrayByRefInitMethodRef =
                byRefController.GetArrayByRefCtorMethodRef(operand);

            codeGenerator
            .Add(OpCodes._new, arrayByRefNameClass, e)
            .Add(OpCodes.dup, null, e);

            CompileExpression(e.Arguments[0], ExpectType.Reference);    //array
            CompileExpression(e.Arguments[1], ExpectType.Primitive);    //index

            codeGenerator.Add(OpCodes.invokespecial, arrayByRefInitMethodRef, e);
        }
Пример #6
0
        private void CompileIntrinsicCreatePointerToArray(ILExpression e)
        {
            InterMethod operand = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments);
            InterType   refType = operand.GenericArguments[0].Type;

            string arrayByRefName = byRefController.GetArrayByRefTypeName(refType);

            Java.Constants.Class arrayByRefNameClass =
                new Java.Constants.Class(namesController.TypeNameToJava(arrayByRefName));
            Java.Constants.MethodRef arrayByRefInitMethodRef =
                byRefController.GetArrayByRefCtorMethodRef(refType);

            codeGenerator
            .Add(OpCodes._new, arrayByRefNameClass, e)
            .Add(OpCodes.dup, null, e);

            CompileExpression(e.Arguments[0], ExpectType.Reference);    //array
            CompileExpression(e.Arguments[1], ExpectType.Primitive);    //index

            codeGenerator.Add(OpCodes.invokespecial, arrayByRefInitMethodRef, e);
        }
Пример #7
0
        private void CompileStind(ILExpression e, ExpectType expectType)
        {
            JavaPrimitiveType type = JavaPrimitiveType.Ref;

            if (e.Operand != null)
            {
                InterType operand = resolver.Resolve((TypeReference)e.Operand, thisMethod.FullGenericArguments);

                if ((operand.IsPrimitive) && ((operand.PrimitiveType == PrimitiveType.Byte) ||
                                              (operand.PrimitiveType == PrimitiveType.SByte)))
                {
                    operand = resolver.Resolve(e.Arguments[0].InferredType, thisMethod.FullGenericArguments).ElementType;
                }

                type = JavaHelpers.InterTypeToJavaPrimitive(operand);
            }

            bool needDup = ((e.ExpectedType != null) && (expectType != ExpectType.None));

            CompileExpression(e.Arguments[0], ExpectType.ByRef);
            CompileExpression(e.Arguments[1], GetExpectType(type));

            Java.Constants.MethodRef setMethodRef = byRefController.GetByRefSetValueMethodRef(type);

            if (needDup)
            {
                if (type.IsDoubleSlot())
                {
                    codeGenerator.Add(OpCodes.dup2_x1, null, e);
                }
                else
                {
                    codeGenerator.Add(OpCodes.dup_x1, null, e);
                }
            }

            codeGenerator.Add(OpCodes.invokevirtual, setMethodRef, e);
        }
Пример #8
0
        public ConstantPool Read(BinaryReader Reader)
        {
            ushort Count = Reader.ReadUInt16BE();

            ResultPool     = new ConstantPool();
            FiledConsts    = new bool[Count];
            FiledConsts[0] = true;
            RawData        = new byte[Count][];

            for (int i = 1; i < Count; i++)
            {
                Constant    Result = null;
                ConstantTag Tag    = (ConstantTag)Reader.ReadByte();

                switch (Tag)
                {
                case ConstantTag.Utf8:                  Result = new Constants.Utf8(); break;

                case ConstantTag.Integer:               Result = new Constants.Integer(); break;

                case ConstantTag.Float:                 Result = new Constants.Float(); break;

                case ConstantTag.Long:                  Result = new Constants.Long(); break;

                case ConstantTag.Double:                Result = new Constants.Double(); break;

                case ConstantTag.Class:                 Result = new Constants.Class(); break;

                case ConstantTag.String:                Result = new Constants.String(); break;

                case ConstantTag.FieldRef:              Result = new Constants.FieldRef(); break;

                case ConstantTag.MethodRef:             Result = new Constants.MethodRef(); break;

                case ConstantTag.InterfaceMethodRef:    Result = new Constants.InterfaceMethodRef(); break;

                case ConstantTag.NameAndType:           Result = new Constants.NameAndType(); break;

                case ConstantTag.MethodHandle:          Result = new Constants.MethodHandle(); break;

                case ConstantTag.MethodType:            Result = new Constants.MethodType(); break;

                case ConstantTag.InvokeDynamic:         Result = new Constants.InvokeDynamic(); break;
                }

                if (Result == null)
                {
                    ResultPool.ForceAddConstant(new Constants.Skip(), (ushort)i);
                    Messages.Message(MessageCode.JavaUnknownConstantTag, ((byte)Tag).ToString());
                    continue;
                }

                RawData[i] = Result.ReadData(Reader);
                ResultPool.ForceAddConstant(Result, (ushort)i);
                if (Result.Is8Byte())
                {
                    FiledConsts[++i] = true;
                }
            }

            for (int i = 1; i < Count; i++)
            {
                GetFilledConstant((ushort)i);
            }

            return(ResultPool);
        }
Пример #9
0
        private void CompileTryBlock(ILTryCatchBlock block)
        {
            string labelsSufix = rnd.Next().ToString();

            string tryStartLabel     = "tryStart" + labelsSufix;
            string tryEndLabel       = "tryEnd" + labelsSufix;
            string handlerStartLabel = "handler" + labelsSufix;
            string exitLabel         = "exit" + labelsSufix;
            string rethrowLabel      = "rethrow" + labelsSufix;

            codeGenerator.Label(tryStartLabel);
            CompileBlock(block.TryBlock);

            if (block.TryBlock.Body.Count == 0)
            {
                codeGenerator.Add(Java.OpCodes.nop, null, block);
            }

            codeGenerator.Label(tryEndLabel);


            if ((block.FinallyBlock != null) || (block.FaultBlock != null))
            {
                int handlerExceptionVar = GetNextFreeVar(JavaPrimitiveType.Ref);

                endfinallyLabels.Push(exitLabel);
                if (block.FinallyBlock != null)
                {
                    CompileBlock(block.FinallyBlock);
                }
                endfinallyLabels.Pop();

                codeGenerator
                .Add(Java.OpCodes._goto, exitLabel, block)
                .Label(handlerStartLabel)
                .AddStore(JavaPrimitiveType.Ref, handlerExceptionVar, block);

                endfinallyLabels.Push(rethrowLabel);
                CompileBlock(block.FinallyBlock ?? block.FaultBlock);
                endfinallyLabels.Pop();

                codeGenerator
                .Label(rethrowLabel)
                .AddLoad(JavaPrimitiveType.Ref, handlerExceptionVar, block)
                .Add(Java.OpCodes.athrow, null, block)
                .Label(exitLabel);

                FreeVar(handlerExceptionVar, JavaPrimitiveType.Ref);

                exceptions.Add(new ExceptionDescription()
                {
                    TryStart     = tryStartLabel,
                    TryEnd       = tryEndLabel,
                    HandlerStart = handlerStartLabel,
                    HandlerType  = null
                });
            }
            else if (block.CatchBlocks.Count > 0)
            {
                codeGenerator.Add(Java.OpCodes._goto, exitLabel, block);

                int index = 0;
                foreach (ILTryCatchBlock.CatchBlock cblock in block.CatchBlocks)
                {
                    string catchHandlerStartLabel = handlerStartLabel + (index++).ToString();
                    int    varIndex = GetVarIndex(cblock.ExceptionVariable ?? new ILVariable {
                        Name = "tmp_Exception", Type = cblock.ExceptionType, IsGenerated = true
                    });
                    InterType catchType = resolver.Resolve(cblock.ExceptionType, thisMethod.FullGenericArguments);

                    Java.Constants.Class catchTypeRef = new Java.Constants.Class(namesController.TypeNameToJava(catchType));

                    foreach (string javaException in catchType.JavaExceptions)
                    {
                        Java.Constants.MethodRef catchTypeInitRef = new Java.Constants.MethodRef(
                            catchTypeRef.Value, ClassNames.JavaConstructorMethodName, "(L" + namesController.TypeNameToJava(
                                javaException) + ";)V");

                        string javaExceptionLabel = catchHandlerStartLabel + javaException;

                        codeGenerator
                        .Label(javaExceptionLabel)
                        .AddStore(JavaPrimitiveType.Ref, varIndex, block)
                        .Add(Java.OpCodes._new, catchTypeRef, block)
                        .Add(Java.OpCodes.dup, null, block)
                        .AddLoad(JavaPrimitiveType.Ref, varIndex, block)
                        .Add(Java.OpCodes.invokespecial, catchTypeInitRef, block)
                        .Add(Java.OpCodes._goto, catchHandlerStartLabel, block);

                        exceptions.Add(new ExceptionDescription()
                        {
                            TryStart     = tryStartLabel,
                            TryEnd       = tryEndLabel,
                            HandlerStart = javaExceptionLabel,
                            HandlerType  = javaException
                        });
                    }

                    codeGenerator
                    .Label(catchHandlerStartLabel)
                    .AddStore(JavaPrimitiveType.Ref, varIndex);

                    exceptionVar.Push(varIndex);
                    CompileBlock(cblock);
                    exceptionVar.Pop();

                    codeGenerator.Add(Java.OpCodes._goto, exitLabel);

                    exceptions.Add(new ExceptionDescription()
                    {
                        TryStart     = tryStartLabel,
                        TryEnd       = tryEndLabel,
                        HandlerStart = catchHandlerStartLabel,
                        HandlerType  = catchType.Fullname
                    });
                }

                codeGenerator.Label(exitLabel);
            }
        }
Пример #10
0
        private byte[] GenerateMethodProlog()
        {
            codeGenerator = new JavaBytecodeWriter();

            if (thisMethod.IsConstructor)
            {
                if (firstCall != null)
                {
                    CompileExpression(firstCall, ExpectType.Any);
                }
                else if (!thisMethod.IsStatic)
                {
                    string typeName = namesController.TypeNameToJava(thisMethod.DeclaringType.BaseType);
                    if ((thisMethod.DeclaringType.IsValueType) && (thisMethod.Parameters.Count > 0))
                    {
                        //call to this() to initialize all fields
                        typeName = namesController.TypeNameToJava(thisMethod.DeclaringType);
                    }

                    MethodRef superCall = new MethodRef(typeName, ClassNames.JavaConstructorMethodName, "()V");
                    codeGenerator
                    .Add(OpCodes.aload_0)
                    .Add(OpCodes.invokespecial, superCall);
                }

                if (thisMethod.IsStatic)
                {
                    var threadLocalFields = thisMethod.DeclaringType.Fields.Where(F => F.IsStatic && F.IsThreadLocal);

                    foreach (InterField fld in threadLocalFields)
                    {
                        FieldRef fldRef = new FieldRef(
                            namesController.TypeNameToJava(fld.DeclaringType.Fullname),
                            namesController.FieldNameToJava(fld.Name),
                            "L" + namesController.TypeNameToJava(ClassNames.JavaLangThreadLocal.ClassName) + ";");

                        codeGenerator
                        .Add(OpCodes._new, new Java.Constants.Class(namesController.TypeNameToJava(ClassNames.JavaLangThreadLocal.ClassName)))
                        .Add(OpCodes.dup)
                        .Add(OpCodes.invokespecial, ClassNames.JavaLangThreadLocal.CtorMethodRef)
                        .Add(OpCodes.putstatic, fldRef);
                    }
                }

                var valueTypeFields = thisMethod.DeclaringType.Fields
                                      .Where(F => ((F.FieldType.IsValueType) && (F.IsStatic == thisMethod.IsStatic)));
                OpCodes putfield = thisMethod.IsStatic ? OpCodes.putstatic : OpCodes.putfield;

                foreach (InterField fld in valueTypeFields)
                {
                    Java.Constants.Class fldTypeRef = new Java.Constants.Class(
                        namesController.TypeNameToJava(fld.FieldType));
                    MethodRef ctorRef = new MethodRef(fldTypeRef.Value, ClassNames.JavaConstructorMethodName, "()V");
                    FieldRef  fldRef  = new FieldRef(namesController.TypeNameToJava(fld.DeclaringType),
                                                     namesController.FieldNameToJava(fld.Name), namesController.GetFieldDescriptor(fld.FieldType));

                    if (!thisMethod.IsStatic)
                    {
                        codeGenerator.Add(OpCodes.aload_0);
                    }

                    codeGenerator
                    .Add(OpCodes._new, fldTypeRef)
                    .Add(OpCodes.dup)
                    .Add(OpCodes.invokespecial, ctorRef)
                    .Add(putfield, fldRef);
                }
            }

            foreach (ValueTypeVar v in valueTypesVars)
            {
                Java.Constants.Class     typeRef = new Java.Constants.Class(namesController.TypeNameToJava(v.varType));
                Java.Constants.MethodRef ctorRef = new Java.Constants.MethodRef(typeRef.Value,
                                                                                ClassNames.JavaConstructorMethodName, "()V");

                codeGenerator
                .Add(Java.OpCodes._new, typeRef)
                .Add(Java.OpCodes.dup)
                .Add(Java.OpCodes.invokespecial, ctorRef)
                .AddStore(JavaPrimitiveType.Ref, v.varIndex);
            }

            return(codeGenerator.End(constsPool).CodeBytes);
        }
Пример #11
0
        private void CompileCall(ILExpression e, ExpectType expect)
        {
            InterMethod operand = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments);

            if (operand.DeclaringType.Fullname == ClassNames.SystemThreadingMonitor.ClassName)
            {
                if (operand.Name == ClassNames.SystemThreadingMonitor.Enter)
                {
                    CompileMonitorEnter(e);
                    return;
                }

                if (operand.Name == ClassNames.SystemThreadingMonitor.Exit)
                {
                    CompileMonitorExit(e);
                    return;
                }
            }

            // Intrinsics that not poping real arguments
            if (operand.DeclaringType.Fullname == ClassNames.Intrinsics.ClassName)
            {
                if (operand.Name.Contains(ClassNames.Intrinsics.CreatePointerToArray))
                {
                    CompileIntrinsicCreatePointerToArray(e); return;
                }
                if (operand.Name == ClassNames.Intrinsics.GetBoxedDataFromPointer)
                {
                    CompileIntrinsicGetBoxedDataFromPointer(e); return;
                }
                if (operand.Name == ClassNames.Intrinsics.GetClass)
                {
                    CompileIntrinsicGetClass(e); return;
                }
            }

            if ((Program.BoxType == BoxingType.Java) && (operand.DeclaringType.Fullname == ClassNames.CorlibUtils) &&
                (operand.Name == ClassNames.ReboxMethod))
            {
                //Skip CIL2Java.Utils::Rebox in java boxing mode due optimizations
                CompileExpression(e.Arguments[0], expect);
                return;
            }

            if ((operand.IsConstructor) && (operand.DeclaringType.IsValueType) && (operand.Parameters.Count < e.Arguments.Count) &&
                (!thisMethod.IsConstructor))
            {
                // rebuild nodes from `call ctor(getVar(), [params])` to
                // setVar(newObj([params])

                ILExpression getVar = e.Arguments[0];
                e.Arguments.RemoveAt(0);
                e.Code      = ILCode.Newobj;
                getVar.Code = LoadVarInvert[getVar.Code];
                getVar.Arguments.Add(e);
                CompileExpression(getVar, expect);

                return;
            }

            if (operand.DeclaringType.IsArray)
            {
                CompileArrayCall(e, expect);
                return;
            }

            int argIndex = 0;

            if ((operand.HasThis) && (operand.Parameters.Count < e.Arguments.Count))
            {
                if (e.Prefixes != null)
                {
                    ILExpressionPrefix constrained = e.Prefixes.Where(P => P.Code == ILCode.Constrained).FirstOrDefault();
                    if (constrained != null)
                    {
                        InterType thisType = resolver.Resolve((TypeReference)constrained.Operand, thisMethod.FullGenericArguments);

                        if (thisType.IsPrimitive)
                        {
                            e.Arguments[argIndex].Code = GetAddrInvert[e.Arguments[argIndex].Code];
                            e.Arguments[argIndex]      = new ILExpression(ILCode.Box, null, e.Arguments[argIndex]);
                        }
                    }
                }

                CompileExpression(e.Arguments[argIndex++], ExpectType.Reference);
            }

            foreach (InterParameter param in operand.Parameters)
            {
                CompileExpression(e.Arguments[argIndex++], GetExpectType(param));
            }

            if (operand.IsVarArg)
            {
                codeGenerator
                .AddIntConst(e.Arguments.Count - argIndex)
                .Add(OpCodes.anewarray, new Java.Constants.Class(namesController.TypeNameToJava(ClassNames.JavaObject)), e);

                int i = 0;
                while (argIndex < e.Arguments.Count)
                {
                    codeGenerator
                    .Add(OpCodes.dup, null, e)
                    .AddIntConst(i++, e);

                    CompileExpression(e.Arguments[argIndex++], ExpectType.Boxed);
                    codeGenerator.Add(OpCodes.aastore, null, e);
                }
            }

            // Intrinsics that poping real arguments
            if (operand.DeclaringType.Fullname == ClassNames.Intrinsics.ClassName)
            {
                if (operand.Name == ClassNames.Intrinsics.monitorenter)
                {
                    codeGenerator.Add(Java.OpCodes.monitorenter, null, e);
                }
                if (operand.Name == ClassNames.Intrinsics.monitorexit)
                {
                    codeGenerator.Add(Java.OpCodes.monitorexit, null, e);
                }
                if (operand.Name == ClassNames.Intrinsics.lshr)
                {
                    codeGenerator.Add(Java.OpCodes.lshr, null, e);
                }
                if (operand.Name == ClassNames.Intrinsics.lushr)
                {
                    codeGenerator.Add(Java.OpCodes.lushr, null, e);
                }

                // UnsafeTypeConvert skip because:
                // Not any compiling. Just push argument, and it will auto became object type
                return;
            }

            CallType callType = CallType.Virtual;

            if (operand.IsStatic)
            {
                callType = CallType.Static;
            }
            else if (operand.DeclaringType.IsInterface)
            {
                callType = CallType.Interface;
            }
            else if ((operand.IsConstructor) || (operand.IsPrivate) ||
                     ((operand.IsSame(thisMethod)) && (thisMethod.DeclaringType.BaseType == operand.DeclaringType)))
            {
                callType = CallType.Special;
            }

            Java.Constant javaOperand = null;

            if (callType == CallType.Interface)
            {
                javaOperand = new Java.Constants.InterfaceMethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }
            else
            {
                javaOperand = new Java.Constants.MethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }

            switch (callType)
            {
            case CallType.Interface:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokeinterface, javaOperand, e));
                break;

            case CallType.Special:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokespecial, javaOperand, e));
                break;

            case CallType.Static:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokestatic, javaOperand, e));
                break;

            case CallType.Virtual:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokevirtual, javaOperand, e));
                break;
            }

            OnRestoreLocalByRefs();

            if ((!operand.ReturnParameter.Type.IsPrimitive) || (operand.ReturnParameter.Type.PrimitiveType != PrimitiveType.Void) ||
                (operand.ReturnParameter.IsBoxed) || (operand.ReturnParameter.IsJavaBoxed))
            {
                TranslateType(operand.ReturnParameter.Type, expect, e);
            }
        }
Пример #12
0
        private void CompileJmp(ILExpression e, ExpectType expect)
        {
            int argIndex = 0;

            if (thisMethod.HasThis)
            {
                codeGenerator.Add(Java.OpCodes.aload_0, null, e);
                argIndex++;
            }

            for (int i = 0; i < thisMethod.Parameters.Count; i++)
            {
                JavaPrimitiveType jp = JavaHelpers.InterTypeToJavaPrimitive(thisMethod.Parameters[i].Type);
                codeGenerator.AddLoad(jp, argIndex++);
                if (jp.IsDoubleSlot())
                {
                    argIndex++;
                }
            }

            InterMethod operand = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments);

            CallType callType = CallType.Virtual;

            if (operand.IsStatic)
            {
                callType = CallType.Static;
            }
            else if (operand.DeclaringType.IsInterface)
            {
                callType = CallType.Interface;
            }
            else if ((operand.IsConstructor) || (operand.IsPrivate) ||
                     ((operand.IsSame(thisMethod)) && (thisMethod.DeclaringType.BaseType == operand.DeclaringType)))
            {
                callType = CallType.Special;
            }

            Java.Constant javaOperand = null;

            if (callType == CallType.Interface)
            {
                javaOperand = new Java.Constants.InterfaceMethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }
            else
            {
                javaOperand = new Java.Constants.MethodRef(
                    namesController.TypeNameToJava(operand.DeclaringType),
                    namesController.MethodNameToJava(operand.NewName),
                    namesController.GetMethodDescriptor(operand));
            }

            switch (callType)
            {
            case CallType.Interface:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokeinterface, javaOperand, e));
                break;

            case CallType.Special:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokespecial, javaOperand, e));
                break;

            case CallType.Static:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokestatic, javaOperand, e));
                break;

            case CallType.Virtual:
                codeGenerator.AddInstruction(new JavaInstruction(Java.OpCodes.invokevirtual, javaOperand, e));
                break;
            }

            codeGenerator.AddReturn(JavaHelpers.InterTypeToJavaPrimitive(thisMethod.ReturnParameter.Type));
        }
Пример #13
0
        private void LinkPass1(Java.ConstantPool pool)
        {
            int offset = StartOffset;

            bool lastWide = false;

            for (int i = 0; i < outputCode.Count; i++)
            {
                JavaInstruction instr = outputCode[i];
                outputCodeOffsets.Add(instr, offset);

                object lastOperand = instr.Operand;
                if (instr.Operand is Java.Constant)
                {
                    instr.Operand = pool.AddConstant((Java.Constant)instr.Operand);
                }
                else if (instr.Operand is MultianewarrayOperand)
                {
                    MultianewarrayOperand operand = (MultianewarrayOperand)instr.Operand;
                    instr.Operand = pool.AddConstant(operand.ClassOperand) | (operand.DimensionsOperand << 16);
                }

                if (instr.Opcode == Java.OpCodes.ldc)
                {
                    if (((ushort)instr.Operand) > byte.MaxValue)
                    {
                        instr.Opcode = Java.OpCodes.ldc_w;
                    }
                }

                if (instr.Opcode == Java.OpCodes.invokeinterface)
                {
                    if (lastOperand is Java.Constants.MethodRef)
                    {
                        Java.Constants.MethodRef m = (Java.Constants.MethodRef)lastOperand;

                        lastOperand = new Java.Constants.InterfaceMethodRef(m.Class, m.Name, m.Descriptor);
                    }

                    byte   argsCount  = CalculateInterfaceCallArgsCount(((Java.Constants.InterfaceMethodRef)lastOperand).Descriptor);
                    ushort constIndex = (ushort)instr.Operand;
                    instr.Operand = (uint)(constIndex | ((argsCount + 1) << 24));
                }

                int size = Java.ByteCode.JavaInstructions[instr.Opcode].Size;
                if ((size == -1) && (instr.Opcode == Java.OpCodes.lookupswitch))
                {
                    LookupswitchOperand op = (LookupswitchOperand)lastOperand;
                    instr.Operand = op;

                    int paddingLendth = (4 - ((offset + 1) % 4)) % 4;

                    size = 1                      //opcode
                           + paddingLendth        //padding
                           + 4                    //default
                           + 4                    //npairs
                           + op.Pairs.Length * 8; //pairs count * pairs size (8 = 4 + 4)
                }

                if (lastWide)
                {
                    size     = (size - 1) * 2 + 1;
                    lastWide = false;
                }

                offset += size;

                if (instr.Opcode == Java.OpCodes.wide)
                {
                    lastWide = true;
                }
            }
        }
Пример #14
0
        private void GenerateArrayByRefType(JavaPrimitiveType type)
        {
            GenerateBaseByRefType(type);

            string valueFieldDesc = "L" + TypeNameToJava(ClassNames.JavaObject) + ";";

            if (type != JavaPrimitiveType.Ref)
            {
                valueFieldDesc = JavaPrimitive2FieldChar[(int)type].ToString();
            }

            Java.Class javaClass = new Java.Class();
            javaClass.AccessFlag = Java.ClassAccessFlag.Final | Java.ClassAccessFlag.Public | Java.ClassAccessFlag.Super;
            javaClass.ThisClass  = TypeNameToJava(new JavaByRefType(ByRefPlace.Array, type).ToString());
            javaClass.SuperClass = TypeNameToJava(new JavaByRefType(ByRefPlace.Unknown, type).ToString());

            Field arrayField = new Field();

            arrayField.AccessFlags = FieldAccessFlags.Private;
            arrayField.Name        = "array";
            arrayField.Descriptor  = "[" + valueFieldDesc;
            javaClass.Fields.Add(arrayField);
            FieldRef arrayFieldRef = new FieldRef(javaClass.ThisClass, arrayField.Name, arrayField.Descriptor);

            Field indexField = new Field();

            indexField.AccessFlags = FieldAccessFlags.Private;
            indexField.Name        = "index";
            indexField.Descriptor  = "I";
            javaClass.Fields.Add(indexField);
            FieldRef indexFieldRef = new FieldRef(javaClass.ThisClass, indexField.Name, indexField.Descriptor);

            Field valueField = new Field();

            valueField.AccessFlags = FieldAccessFlags.Private;
            valueField.Name        = "value";
            valueField.Descriptor  = valueFieldDesc;
            javaClass.Fields.Add(valueField);
            FieldRef valueFieldRef = new FieldRef(javaClass.ThisClass, valueField.Name, valueField.Descriptor);

            Java.Constants.MethodRef superCtorRef =
                new Java.Constants.MethodRef(javaClass.SuperClass, ClassNames.JavaConstructorMethodName, "()V");

            Method ctorMethod = new Method();

            ctorMethod.AccessFlags = MethodAccessFlags.Public;
            ctorMethod.Name        = ClassNames.JavaConstructorMethodName;
            ctorMethod.Descriptor  = "(" + arrayField.Descriptor + "I)V";
            ctorMethod.Attributes.Add(new JavaBytecodeWriter()
                                      .Add(OpCodes.aload_0)
                                      .Add(OpCodes.invokespecial, superCtorRef)

                                      //this.array = array
                                      .Add(OpCodes.aload_0)
                                      .Add(OpCodes.aload_1)
                                      .Add(OpCodes.putfield, arrayFieldRef)

                                      //this.index = index
                                      .Add(OpCodes.aload_0)
                                      .Add(OpCodes.iload_2)
                                      .Add(OpCodes.putfield, indexFieldRef)

                                      //this.value = array[index]
                                      .Add(OpCodes.aload_0)
                                      .Add(OpCodes.aload_1)
                                      .Add(OpCodes.iload_2)
                                      .AddArrayLoad(JavaHelpers.JavaPrimitiveToArrayType(type))
                                      .Add(OpCodes.putfield, valueFieldRef)

                                      .Add(OpCodes._return)

                                      .End(javaClass.ConstantPool));
            javaClass.Methods.Add(ctorMethod);

            Java.Method getMethod = new Method();
            getMethod.AccessFlags = Java.MethodAccessFlags.Public;
            getMethod.Name        = ClassNames.ByRef.GetValueMethodName;
            getMethod.Descriptor  = "()" + valueFieldDesc;
            getMethod.Attributes.Add(new JavaBytecodeWriter()
                                     //return this.value
                                     .Add(OpCodes.aload_0)
                                     .Add(OpCodes.getfield, valueFieldRef)
                                     .AddReturn(type)
                                     .End(javaClass.ConstantPool));
            javaClass.Methods.Add(getMethod);

            Java.Method setMethod = new Method();
            setMethod.AccessFlags = MethodAccessFlags.Public;
            setMethod.Name        = ClassNames.ByRef.SetValueMethodName;
            setMethod.Descriptor  = "(" + valueFieldDesc + ")V";
            setMethod.Attributes.Add(new JavaBytecodeWriter()
                                     //this.array[this.index] = value
                                     .Add(OpCodes.aload_0)
                                     .Add(OpCodes.getfield, arrayFieldRef)
                                     .Add(OpCodes.aload_0)
                                     .Add(OpCodes.getfield, indexFieldRef)
                                     .AddLoad(type, 1)
                                     .AddArrayStore(JavaHelpers.JavaPrimitiveToArrayType(type))

                                     //this.value = value
                                     .Add(OpCodes.aload_0)
                                     .AddLoad(type, 1)
                                     .Add(OpCodes.putfield, valueFieldRef)

                                     .AddReturn(JavaPrimitiveType.Void)

                                     .End(javaClass.ConstantPool));
            javaClass.Methods.Add(setMethod);

            WriteClass(javaClass);
        }
Пример #15
0
        private void GenerateLocalByRefType(JavaPrimitiveType type)
        {
            GenerateBaseByRefType(type);

            string valueFieldDesc = "L" + TypeNameToJava(ClassNames.JavaObject) + ";";

            if (type != JavaPrimitiveType.Ref)
            {
                valueFieldDesc = JavaPrimitive2FieldChar[(int)type].ToString();
            }

            Java.Class javaClass = new Java.Class();
            javaClass.AccessFlag = Java.ClassAccessFlag.Final | Java.ClassAccessFlag.Public | Java.ClassAccessFlag.Super;
            javaClass.ThisClass  = TypeNameToJava(new JavaByRefType(ByRefPlace.Local, type).ToString());
            javaClass.SuperClass = TypeNameToJava(new JavaByRefType(ByRefPlace.Unknown, type).ToString());

            Java.Field valueField = new Java.Field();
            valueField.AccessFlags = Java.FieldAccessFlags.Private;
            valueField.Name        = "value";
            valueField.Descriptor  = valueFieldDesc;
            javaClass.Fields.Add(valueField);

            Java.Constants.FieldRef  valueRef     = new Java.Constants.FieldRef(javaClass.ThisClass, "value", valueFieldDesc);
            Java.Constants.MethodRef superCtorRef =
                new Java.Constants.MethodRef(javaClass.SuperClass, ClassNames.JavaConstructorMethodName, "()V");

            Java.Method ctor = new Java.Method();
            ctor.AccessFlags = Java.MethodAccessFlags.Public;
            ctor.Name        = ClassNames.JavaConstructorMethodName;
            ctor.Descriptor  = "(" + valueFieldDesc + ")V";
            ctor.Attributes.Add(new JavaBytecodeWriter()
                                .Add(OpCodes.aload_0)
                                .Add(OpCodes.invokespecial, superCtorRef)
                                .Add(OpCodes.aload_0)
                                .AddLoad(type, 1)
                                .Add(OpCodes.putfield, valueRef)
                                .AddReturn(JavaPrimitiveType.Void)
                                .End(javaClass.ConstantPool)
                                );
            javaClass.Methods.Add(ctor);

            Java.Method get = new Method();
            get.AccessFlags = Java.MethodAccessFlags.Public;
            get.Name        = ClassNames.ByRef.GetValueMethodName;
            get.Descriptor  = "()" + valueFieldDesc;
            get.Attributes.Add(new JavaBytecodeWriter()
                               .Add(OpCodes.aload_0)
                               .Add(OpCodes.getfield, valueRef)
                               .AddReturn(type)
                               .End(javaClass.ConstantPool));
            javaClass.Methods.Add(get);

            Java.Method set = new Method();
            set.AccessFlags = MethodAccessFlags.Public;
            set.Name        = ClassNames.ByRef.SetValueMethodName;
            set.Descriptor  = "(" + valueFieldDesc + ")V";
            set.Attributes.Add(new JavaBytecodeWriter()
                               .Add(OpCodes.aload_0)
                               .AddLoad(type, 1)
                               .Add(OpCodes.putfield, valueRef)
                               .AddReturn(JavaPrimitiveType.Void)
                               .End(javaClass.ConstantPool));
            javaClass.Methods.Add(set);

            WriteClass(javaClass);
        }
Пример #16
0
        protected override bool CompareEqwals(Constant c)
        {
            MethodRef Another = (MethodRef)c;

            return((Class == Another.Class) && (Name == Another.Name) && (Descriptor == Another.Descriptor));
        }