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); }
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); }
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 }
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")); } }
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); }
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); }
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); }
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); }
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); } }
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); }
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 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 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; } } }
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); }
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); }
protected override bool CompareEqwals(Constant c) { MethodRef Another = (MethodRef)c; return((Class == Another.Class) && (Name == Another.Name) && (Descriptor == Another.Descriptor)); }