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)); }
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); } }
private Java.Field CompileField(InterField field) { Messages.Verbose(" Compiling field {0}...", field.ToString()); Java.Field result = new Java.Field(); if (field.IsPublic) { result.AccessFlags |= Java.FieldAccessFlags.Public; } else if (field.IsProtected) { result.AccessFlags |= Java.FieldAccessFlags.Protected; } else { result.AccessFlags |= Java.FieldAccessFlags.Private; } if (field.IsStatic) { result.AccessFlags |= Java.FieldAccessFlags.Static; } //if it will be readonly, we will get error in CopyTo method of ValueType if (((field.IsReadonly) || (field.IsLiteral)) && (!field.DeclaringType.IsValueType)) { result.AccessFlags |= Java.FieldAccessFlags.Final; } if (field.IsVolatile) { result.AccessFlags |= Java.FieldAccessFlags.Volatile; } result.Name = FieldNameToJava(field.Name); result.Descriptor = GetFieldDescriptor(field.FieldType); if ((field.IsStatic) && (field.IsThreadLocal)) { result.Descriptor = "L" + TypeNameToJava(ClassNames.JavaLangThreadLocal.ClassName) + ";"; } if (field.Constatnt != null) { Java.Constant constVal = null; if (field.Constatnt is byte) { constVal = new Java.Constants.Integer((byte)field.Constatnt); } else if (field.Constatnt is sbyte) { constVal = new Java.Constants.Integer((sbyte)field.Constatnt); } else if (field.Constatnt is short) { constVal = new Java.Constants.Integer((short)field.Constatnt); } else if (field.Constatnt is ushort) { constVal = new Java.Constants.Integer((ushort)field.Constatnt); } else if (field.Constatnt is int) { constVal = new Java.Constants.Integer((int)field.Constatnt); } else if (field.Constatnt is uint) { constVal = new Java.Constants.Integer(unchecked ((int)((uint)field.Constatnt))); } else if (field.Constatnt is char) { constVal = new Java.Constants.Integer((char)field.Constatnt); } else if (field.Constatnt is bool) { constVal = new Java.Constants.Integer((bool)field.Constatnt ? 1 : 0); } else if (field.Constatnt is long) { constVal = new Java.Constants.Long((long)field.Constatnt); } else if (field.Constatnt is ulong) { constVal = new Java.Constants.Long(unchecked ((long)((ulong)field.Constatnt))); } else if (field.Constatnt is float) { constVal = new Java.Constants.Float((float)field.Constatnt); } else if (field.Constatnt is double) { constVal = new Java.Constants.Double((double)field.Constatnt); } else if (field.Constatnt is string) { constVal = new Java.Constants.String((string)field.Constatnt); } if (constVal != null) { result.Attributes.Add(new Java.Attributes.ConstantValue(constVal)); } } return(result); }