private void GenerateValueTypeGetCopy(InterType type) { Method result = new Method(); result.AccessFlags = MethodAccessFlags.Public; result.Name = ClassNames.ValueTypeGetCopy; result.Descriptor = "()" + GetFieldDescriptor(type); Java.Constants.Class typeRef = new Java.Constants.Class(TypeNameToJava(type.Fullname)); MethodRef defaultCtorRef = new MethodRef(typeRef.Value, ClassNames.JavaConstructorMethodName, "()V"); MethodRef copyToRef = new MethodRef(typeRef.Value, ClassNames.ValueTypeCopyTo, "(" + GetFieldDescriptor(type) + ")V"); result.Attributes.Add(new JavaBytecodeWriter() //tmp = new type(); .Add(OpCodes._new, typeRef) .Add(OpCodes.dup) .Add(OpCodes.invokespecial, defaultCtorRef) .Add(OpCodes.astore_1) //this.CopyTo(tmp) .Add(OpCodes.aload_0) .Add(OpCodes.aload_1) .Add(OpCodes.invokevirtual, copyToRef) //return tmp .Add(OpCodes.aload_1) .AddReturn(JavaPrimitiveType.Ref) .End(currentJavaClass.ConstantPool)); currentJavaClass.Methods.Add(result); }
private void CompileIsinst(ILExpression e, ExpectType expect) { InterType operand = resolver.Resolve((TypeReference)e.Operand, thisMethod.FullGenericArguments); CompileExpression(e.Arguments[0], ExpectType.Reference); // dup // instanceof operand // ifne :end // pop // aconst_null //:end // checkcast operand string endLabel = rnd.Next().ToString() + "end"; Java.Constants.Class operandRef = new Java.Constants.Class(namesController.TypeNameToJava(GetBoxType(operand))); codeGenerator .Add(Java.OpCodes.dup, null, e) .Add(Java.OpCodes.instanceof, operandRef, e) .Add(Java.OpCodes.ifne, endLabel, e) .Add(Java.OpCodes.pop, null, e) .Add(Java.OpCodes.aconst_null, null, e) .Label(endLabel) .Add(Java.OpCodes.checkcast, operandRef, e); }
public JavaBytecodeWriter AddMultianewarray(Java.Constants.Class arrayType, byte dimensions, object tag) { return(Add(Java.OpCodes.multianewarray, new MultianewarrayOperand() { ClassOperand = arrayType, DimensionsOperand = dimensions }, tag)); }
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 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 TranslateType(InterType type, ExpectType expected, object tag) { if ((Program.Unsigned) && (type.IsPrimitive) && (type.PrimitiveType.IsUnsigned())) { if ((type.PrimitiveType == PrimitiveType.Byte) || (type.PrimitiveType == PrimitiveType.UInt16)) { if (type.PrimitiveType == PrimitiveType.Byte) { codeGenerator.AddIntConst(0xff, tag); } else { codeGenerator.AddIntConst(0xffff, tag); } codeGenerator.Add(Java.OpCodes.iand, null, tag); } } if (expected == ExpectType.Any) { return; } if (expected == ExpectType.None) { codeGenerator.AddPop(JavaHelpers.InterTypeToJavaPrimitive(type), tag); } if ((type.IsByRef) && (expected != ExpectType.ByRef) && (!type.ElementType.IsValueType)) { JavaPrimitiveType javaType = JavaHelpers.InterTypeToJavaPrimitive(type.ElementType); MethodRef getMethodRef = byRefController.GetByRefGetValueMethodRef(javaType); Java.Constants.Class loadedTypeRef = new Java.Constants.Class(namesController.TypeNameToJava(type.ElementType)); codeGenerator.Add(OpCodes.invokevirtual, getMethodRef, tag); if (javaType == JavaPrimitiveType.Ref) { codeGenerator.Add(OpCodes.checkcast, loadedTypeRef, tag); } type = type.ElementType; } if (((expected == ExpectType.Boxed) || (expected == ExpectType.Reference)) && ((type.IsPrimitive) || (type.IsEnum) || (type.IsValueType))) { if ((!type.IsNullable) || (expected != ExpectType.Reference)) { BoxType(type, tag); } } }
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 CompileLdflda(ILExpression e, ExpectType expectType) { InterField operand = resolver.Resolve((FieldReference)e.Operand, thisMethod.FullGenericArguments); if ((operand.FieldType.IsValueType) || ((operand.FieldType.IsPrimitive) && (expectType == ExpectType.Reference))) { if (e.Code == ILCode.Ldflda) { CompileExpression(e.Arguments[0], ExpectType.Reference); } CompileFieldLoad(operand, e); if (operand.FieldType.IsPrimitive) { TranslateType(operand.FieldType, ExpectType.Boxed, e); } return; } string byRefTypeName = byRefController.GetFieldByRefTypeName(operand.FieldType); Java.Constants.Class constByRefType = new Java.Constants.Class(namesController.TypeNameToJava(byRefTypeName)); Java.Constants.Class constFieldDeclClass = new Java.Constants.Class(namesController.TypeNameToJava(operand.DeclaringType)); Java.Constants.String constFieldName = new Java.Constants.String( namesController.FieldNameToJava(operand.Name)); MethodRef constFieldByRefCtorRef = byRefController.GetFieldByRefCtorMethodRef(operand.FieldType); codeGenerator.Add(OpCodes._new, constByRefType, e); codeGenerator.Add(OpCodes.dup, null, e); if (e.Code == ILCode.Ldflda) { CompileExpression(e.Arguments[0], ExpectType.Reference); } else { codeGenerator.Add(OpCodes.aconst_null, null, e); } codeGenerator.Add(OpCodes.ldc, constFieldDeclClass, e); codeGenerator.Add(OpCodes.ldc, constFieldName, e); codeGenerator.Add(OpCodes.invokevirtual, ClassNames.JavaLangClass.getDeclaredFieldRef, e); codeGenerator.Add(OpCodes.invokespecial, constFieldByRefCtorRef); }
private void GenerateStaticCtor(InterType type) { Method ctor = new Method(); ctor.AccessFlags = MethodAccessFlags.Static; ctor.Name = "<clinit>"; ctor.Descriptor = "()V"; JavaBytecodeWriter codeWriter = new JavaBytecodeWriter(); var threadLocalFields = type.Fields.Where(F => F.IsThreadLocal && F.IsStatic); foreach (InterField fld in threadLocalFields) { FieldRef fldRef = new FieldRef(TypeNameToJava(type.Fullname), FieldNameToJava(fld.Name), "L" + TypeNameToJava(ClassNames.JavaLangThreadLocal.ClassName) + ";"); codeWriter .Add(OpCodes._new, new Java.Constants.Class(TypeNameToJava(ClassNames.JavaLangThreadLocal.ClassName))) .Add(OpCodes.dup) .Add(OpCodes.invokespecial, ClassNames.JavaLangThreadLocal.CtorMethodRef) .Add(OpCodes.putstatic, fldRef); } var staticValueTypeFields = type.Fields.Where(F => ((F.IsStatic) && (F.FieldType.IsValueType))); foreach (InterField fld in staticValueTypeFields) { Java.Constants.Class fldTypeRef = new Java.Constants.Class(TypeNameToJava(fld.FieldType.Fullname)); MethodRef fldTypeInitRef = new MethodRef(fldTypeRef.Value, ClassNames.JavaConstructorMethodName, "()V"); FieldRef fldRef = new FieldRef(TypeNameToJava(type.Fullname), FieldNameToJava(fld.Name), GetFieldDescriptor(fld.FieldType)); codeWriter .Add(OpCodes._new, fldTypeRef) .Add(OpCodes.dup) .Add(OpCodes.invokespecial, fldTypeInitRef) .Add(OpCodes.putstatic, fldRef); } codeWriter.AddReturn(JavaPrimitiveType.Void); ctor.Attributes.Add(codeWriter.End(currentJavaClass.ConstantPool)); currentJavaClass.Methods.Add(ctor); }
private void CompileLdind(ILExpression e, ExpectType expect) { InterType operand = resolver.Resolve((TypeReference)e.Arguments[0].InferredType, thisMethod.FullGenericArguments); CompileExpression(e.Arguments[0], ExpectType.ByRef); MethodRef getMethodRef = byRefController.GetByRefGetValueMethodRef(JavaHelpers.InterTypeToJavaPrimitive( operand.ElementType)); InterType loadType = resolver.Resolve(e.InferredType, thisMethod.FullGenericArguments); Java.Constants.Class loadedTypeRef = new Java.Constants.Class(namesController.TypeNameToJava(loadType)); codeGenerator.Add(OpCodes.invokevirtual, getMethodRef, e); if ((!operand.ElementType.IsPrimitive) && (!operand.ElementType.IsEnum)) { codeGenerator.Add(OpCodes.checkcast, loadedTypeRef, e); } }
private void CompileDefaultValue(ILExpression e, ExpectType expect) { InterType operand = resolver.Resolve((TypeReference)e.Operand, thisMethod.FullGenericArguments); if (operand.IsValueType) { Java.Constants.Class operandRef = new Java.Constants.Class(namesController.TypeNameToJava(operand)); MethodRef operandCtorRef = new MethodRef(operandRef.Value, ClassNames.JavaConstructorMethodName, "()V"); codeGenerator .Add(Java.OpCodes._new, operandRef, e) .Add(Java.OpCodes.dup, null, e) .Add(Java.OpCodes.invokespecial, operandCtorRef, e); } else { codeGenerator.AddDefaultValue(JavaHelpers.InterTypeToJavaPrimitive(operand), e); } TranslateType(operand, expect, e); }
private void CompileNewobj(ILExpression e, ExpectType expect) { InterMethod ctor = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments); if (ctor.DeclaringType.IsArray) { CompileNewmultiarray(e, expect); } else { Java.Constants.Class declTypeClassRef = new Java.Constants.Class( namesController.TypeNameToJava(ctor.DeclaringType)); codeGenerator .Add(Java.OpCodes._new, declTypeClassRef, e) .Add(Java.OpCodes.dup, null, e); CompileCall(e, expect); } }
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 CompileLdftn(ILExpression e, ExpectType expect) { InterMethod operand = resolver.Resolve((MethodReference)e.Operand, thisMethod.FullGenericArguments); string methodPointerClass = GenerateMethodPointerClass(operand); if (Program.MethodPointersType == MethodPointerImplementation.Fast) { Java.Constants.Class mpClassRef = new Java.Constants.Class(namesController.TypeNameToJava(methodPointerClass)); MethodRef mpInitRef = new MethodRef(mpClassRef.Value, ClassNames.JavaConstructorMethodName, "()V"); codeGenerator .Add(OpCodes._new, mpClassRef, e) .Add(OpCodes.dup, null, e) .Add(OpCodes.invokespecial, mpInitRef, e); } else { codeGenerator .Add(OpCodes.ldc, new Java.Constants.String(methodPointerClass.Replace('/', '$'))) .Add(OpCodes.invokestatic, ClassNames.GlobalMethodPointersAdd); } }
private void GenerateValueTypeDefaultCtor(InterType type) { Method result = new Method(); result.AccessFlags = MethodAccessFlags.Public; result.Name = ClassNames.JavaConstructorMethodName; result.Descriptor = "()V"; JavaBytecodeWriter codeWriter = new JavaBytecodeWriter(); codeWriter .Add(OpCodes.aload_0) .Add(OpCodes.invokespecial, ClassNames.ValueTypeCtor); foreach (InterField fld in type.Fields) { if ((fld.FieldType.IsValueType) && (!fld.IsStatic)) { Java.Constants.Class fldTypeClassRef = new Java.Constants.Class(TypeNameToJava(fld.FieldType.Fullname)); MethodRef fldTypeCtorRef = new MethodRef(fldTypeClassRef.Value, "<init>", "()V"); FieldRef fldRef = new FieldRef(TypeNameToJava(type.Fullname), FieldNameToJava(fld.Name), GetFieldDescriptor(fld.FieldType)); codeWriter .Add(OpCodes.aload_0) .Add(OpCodes._new, fldTypeClassRef) .Add(OpCodes.dup) .Add(OpCodes.invokespecial, fldTypeCtorRef) .Add(OpCodes.putfield, fldRef); } } codeWriter.AddReturn(JavaPrimitiveType.Void); result.Attributes.Add(codeWriter.End(currentJavaClass.ConstantPool)); currentJavaClass.Methods.Add(result); }
private void GenerateValueTypeEquals(InterType type) { if (type.Methods.Where(M => ((M.Name == "Equals") && (M.Parameters.Count == 1) && (M.Parameters[0].Type.Fullname == ClassNames.JavaObject))).Count() > 0) { return; } Method result = new Method(); result.AccessFlags = MethodAccessFlags.Public; result.Name = "equals"; result.Descriptor = "(L" + TypeNameToJava(ClassNames.JavaObject) + ";)Z"; Java.Constants.Class thisTypeRef = new Java.Constants.Class(TypeNameToJava(type.Fullname)); JavaBytecodeWriter codeGenerator = new JavaBytecodeWriter(); codeGenerator .Add(OpCodes.aload_1) .Add(OpCodes.instanceof, thisTypeRef) .Add(OpCodes.ifeq, "false") .Add(OpCodes.aload_1) .Add(OpCodes.checkcast, thisTypeRef) .Add(OpCodes.astore_1); foreach (InterField fld in type.Fields) { FieldRef fldRef = new FieldRef(thisTypeRef.Value, FieldNameToJava(fld.Name), GetFieldDescriptor(fld.FieldType)); codeGenerator .Add(OpCodes.aload_0) .Add(OpCodes.getfield, fldRef) .Add(OpCodes.aload_1) .Add(OpCodes.getfield, fldRef); if ((fld.FieldType.IsPrimitive) || (fld.FieldType.IsEnum)) { switch (JavaHelpers.InterTypeToJavaPrimitive(fld.FieldType)) { case JavaPrimitiveType.Bool: case JavaPrimitiveType.Byte: case JavaPrimitiveType.Char: case JavaPrimitiveType.Int: case JavaPrimitiveType.Short: codeGenerator.Add(OpCodes.if_icmpne, "false"); break; case JavaPrimitiveType.Long: codeGenerator.Add(OpCodes.lcmp).Add(OpCodes.ifne, "false"); break; case JavaPrimitiveType.Float: codeGenerator.Add(OpCodes.fcmpg).Add(OpCodes.ifne, "false"); break; case JavaPrimitiveType.Double: codeGenerator.Add(OpCodes.dcmpg).Add(OpCodes.ifne, "false"); break; } } else if (fld.FieldType.IsValueType) { MethodRef equalMethod = new MethodRef(TypeNameToJava(fld.FieldType.Fullname), result.Name, result.Descriptor); codeGenerator.Add(OpCodes.invokevirtual, equalMethod).Add(OpCodes.ifeq, "false"); } else { codeGenerator.Add(OpCodes.if_acmpne, "false"); } } codeGenerator .Add(OpCodes.iconst_1) .Add(OpCodes._goto, "exit") .Label("false") .Add(OpCodes.iconst_0) .Label("exit") .Add(OpCodes.ireturn); result.Attributes.Add(codeGenerator.End(currentJavaClass.ConstantPool)); currentJavaClass.Methods.Add(result); }
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); }
public JavaBytecodeWriter AddMultianewarray(Java.Constants.Class arrayType, byte dimensions) { return(AddMultianewarray(arrayType, dimensions, null)); }
private void CompileUnbox(ILExpression e, ExpectType expect) { InterType operand = resolver.Resolve((TypeReference)e.Operand, thisMethod.FullGenericArguments); if ((operand.IsPrimitive) || (operand.IsEnum)) { string fieldName = ClassNames.BoxedPrimitiveValueFieldName; if (operand.IsEnum) { fieldName = ClassNames.EnumValueFieldName; } // Generating FieldByRef to value field of boxed class // In java boxed primitived has field named "value" too. // Yes, it is bad hack, but I don't known another way to do this string boxedClass = GetBoxType(operand); string byRefTypeName = byRefController.GetFieldByRefTypeName(operand); Java.Constants.Class constByRefType = new Java.Constants.Class(namesController.TypeNameToJava(byRefTypeName)); Java.Constants.Class constFieldDeclClass = new Java.Constants.Class(namesController.TypeNameToJava(operand)); Java.Constants.String constFieldName = new Java.Constants.String( namesController.FieldNameToJava(fieldName)); MethodRef constFieldByRefCtorRef = byRefController.GetFieldByRefCtorMethodRef(operand); codeGenerator.Add(OpCodes._new, constByRefType, e); codeGenerator.Add(OpCodes.dup, null, e); CompileExpression(e.Arguments[0], ExpectType.Boxed); codeGenerator.Add(OpCodes.ldc, constFieldDeclClass, e); codeGenerator.Add(OpCodes.ldc, constFieldName, e); codeGenerator.Add(OpCodes.invokevirtual, ClassNames.JavaLangClass.getDeclaredFieldRef, e); codeGenerator.Add(OpCodes.invokespecial, constFieldByRefCtorRef); } else if (operand.IsNullable) { // From ECMA-335, III.4.32 // [Note: Typically, unbox simply computes the address of the value type that is already present // inside of the boxed object. This approach is not possible when unboxing nullable value types. // Because Nullable<T> values are converted to boxed Ts during the box operation, an // implementation often must manufacture a new Nullable<T> on the heap and compute the address // to the newly allocated object. end note] codeGenerator .Add(OpCodes._new, new Java.Constants.Class(namesController.TypeNameToJava(operand)), e) .Add(OpCodes.dup, null, e); CompileUnbox_Any(e, ExpectType.Any); codeGenerator.Add(OpCodes.invokespecial, new MethodRef( namesController.TypeNameToJava(operand), ClassNames.JavaConstructorMethodName, "(" + namesController.GetFieldDescriptor(operand.GenericArguments[0].Type) + ")V")); } else { // By standart, we must compute a ref to value type from it boxed representation // But in CIL2Java boxed value type is ref to it CompileExpression(e.Arguments[0], ExpectType.Any); } }
private void CompileNewarr(ILExpression e, ExpectType expect) { InterType operand = resolver.Resolve((TypeReference)e.Operand, thisMethod.FullGenericArguments); InterType element = operand; if (element.IsArray) { element = element.ElementType; } Java.Constants.Class operandRef = new Java.Constants.Class(namesController.TypeNameToJava(element)); MethodRef valueTypeInitRef = new MethodRef(operandRef.Value, ClassNames.JavaConstructorMethodName, "()V"); JavaArrayType arrayType = JavaHelpers.InterTypeToJavaArrayType(operand); if (e.Code == ILCode.Newarr) { CompileExpression(e.Arguments[0], ExpectType.Primitive); } else { if (operand.Dimesnsions[0].LowerBound != 0) { Messages.Message(MessageCode.NotZeroLowerBound, operand.Fullname); } codeGenerator.AddIntConst(operand.Dimesnsions[0].UpperBound.Value, e); } if (arrayType == JavaArrayType.Ref) { codeGenerator.Add(Java.OpCodes.anewarray, operandRef, e); } else { codeGenerator.AddNewArray(arrayType, e); } if (e.Code == ILCode.InitArray) { for (int i = 0; i < e.Arguments.Count; i++) { if ((e.Arguments[i].Code == ILCode.DefaultValue) && (!element.IsValueType)) { continue; } codeGenerator.Add(Java.OpCodes.dup, null, e); codeGenerator.AddIntConst(i, e); CompileExpression(e.Arguments[i], GetExpectType(element)); codeGenerator.AddArrayStore(arrayType, e); } } else if (element.IsValueType) { int arrayTmpStore = GetNextFreeVar(JavaPrimitiveType.Ref); int arrayLengthTmp = GetNextFreeVar(JavaPrimitiveType.Int); string labelPrefix = rnd.Next().ToString(); string loopLabel = labelPrefix + "loop"; string endLabel = labelPrefix + "end"; codeGenerator .AddStore(JavaPrimitiveType.Ref, arrayTmpStore, e) .AddLoad(JavaPrimitiveType.Ref, arrayTmpStore, e) .Add(Java.OpCodes.arraylength, null, e) .AddStore(JavaPrimitiveType.Int, arrayLengthTmp, e) // while (arrayLengthTmp > 0) arrayTmpStore[--arrayLengthTmp] = new valType(); .Label(loopLabel) .AddLoad(JavaPrimitiveType.Int, arrayLengthTmp, e) .Add(Java.OpCodes.ifle, endLabel, e) .AddIInc((ushort)arrayLengthTmp, -1, e) .AddLoad(JavaPrimitiveType.Ref, arrayTmpStore, e) .AddLoad(JavaPrimitiveType.Int, arrayLengthTmp, e) .Add(Java.OpCodes._new, operandRef, e) .Add(Java.OpCodes.dup, null, e) .Add(Java.OpCodes.invokespecial, valueTypeInitRef, e) .Add(Java.OpCodes.aastore, null, e) .Add(Java.OpCodes._goto, loopLabel, e) .Label(endLabel) .AddLoad(JavaPrimitiveType.Ref, arrayTmpStore, e); FreeVar(arrayTmpStore, JavaPrimitiveType.Ref); FreeVar(arrayLengthTmp, JavaPrimitiveType.Int); } }
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 CompileDelegateInvoke(InterType type) { Method result = new Method(); result.AccessFlags = MethodAccessFlags.Public | MethodAccessFlags.Final; result.Name = ClassNames.DelegateInvokeMethodName; result.Descriptor = GetMethodDescriptor(type.Methods.Where(M => M.Name == ClassNames.DelegateInvokeMethodName) .FirstOrDefault()); JavaBytecodeWriter codeWriter = new JavaBytecodeWriter(); Java.Constants.Class methodPointerType = new Java.Constants.Class( TypeNameToJava(((INamesController)this).GetMethodPointerInterface( type.Methods.Where(M => M.Name == ClassNames.DelegateInvokeMethodName).FirstOrDefault()))); InterMethod invokeMethod = type.Methods.Where(M => M.Name == ClassNames.DelegateInvokeMethodName).FirstOrDefault(); codeWriter .Add(OpCodes.aload_0) .Add(OpCodes.getfield, ClassNames.DelegateMethodFieldFast); if (Program.MethodPointersType == MethodPointerImplementation.Standart) { MethodRef unboxRef = Program.AsX64 ? ClassNames.JavaLongUnbox : ClassNames.JavaIntegerUnbox; codeWriter .Add(OpCodes.checkcast, new Java.Constants.Class(unboxRef.Class)) .Add(OpCodes.invokevirtual, unboxRef); if (Program.AsX64) { codeWriter.Add(OpCodes.l2i); } codeWriter.Add(OpCodes.invokestatic, ClassNames.GlobalMethodPointersGet); } codeWriter .Add(OpCodes.checkcast, methodPointerType) .Add(OpCodes.aload_0) .Add(OpCodes.getfield, ClassNames.DelegateTargetField); for (int i = 0; i < invokeMethod.Parameters.Count; i++) { codeWriter.AddLoad(JavaHelpers.InterTypeToJavaPrimitive(invokeMethod.Parameters[i].Type), i + 1); } codeWriter.Add(OpCodes.invokeinterface, new InterfaceMethodRef(methodPointerType.Value, ClassNames.MethodPointerInvokeName, "(L" + TypeNameToJava(ClassNames.JavaObject) + ";" + GetMethodDescriptor(invokeMethod).Substring(1))); if (type.BaseType.Fullname == ClassNames.MulticastDelegateTypeName) { codeWriter .Add(OpCodes.aload_0) .Add(OpCodes.getfield, ClassNames.MulticastDelegateNextField) .Add(OpCodes.ifnull, "exit"); if (invokeMethod.ReturnParameter.Type.PrimitiveType != PrimitiveType.Void) { codeWriter.Add(OpCodes.pop); } codeWriter .Add(OpCodes.aload_0) .Add(OpCodes.getfield, ClassNames.MulticastDelegateNextField) .Add(OpCodes.checkcast, new Java.Constants.Class(TypeNameToJava(type.Fullname))); for (int i = 0; i < invokeMethod.Parameters.Count; i++) { codeWriter.AddLoad(JavaHelpers.InterTypeToJavaPrimitive(invokeMethod.Parameters[i].Type), i + 1); } codeWriter.Add(OpCodes.invokevirtual, new MethodRef(TypeNameToJava(type.Fullname), ClassNames.DelegateInvokeMethodName, GetMethodDescriptor(invokeMethod))); } codeWriter .Label("exit") .AddReturn(JavaHelpers.InterTypeToJavaPrimitive(invokeMethod.ReturnParameter.Type)); result.Attributes.Add(codeWriter.End(currentJavaClass.ConstantPool)); currentJavaClass.Methods.Add(result); }