Beispiel #1
0
 public void AddPrefix(ILExpressionPrefix prefix)
 {
     ILExpressionPrefix[] arr = this.Prefixes;
     if (arr == null)
     {
         arr = new ILExpressionPrefix[1];
     }
     else
     {
         Array.Resize(ref arr, arr.Length + 1);
     }
     arr[arr.Length - 1] = prefix;
     this.Prefixes       = arr;
 }
		/// <summary>
		/// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified,
		/// returns the constrained type wrapped in a ByReferenceType.
		/// </summary>
		TypeReference MakeRefIfValueType(TypeReference type, ILExpressionPrefix constrainedPrefix)
		{
			if (constrainedPrefix != null)
				return new ByReferenceType((TypeReference)constrainedPrefix.Operand);
			if (type.IsValueType)
				return new ByReferenceType(type);
			else
				return type;
		}
Beispiel #3
0
		/// <summary>
		/// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified,
		/// returns the constrained type wrapped in a ByReferenceType.
		/// </summary>
		TypeSig MakeRefIfValueType(TypeSig type, ILExpressionPrefix constrainedPrefix)
		{
			if (constrainedPrefix != null)
				return new ByRefSig((constrainedPrefix.Operand as ITypeDefOrRef).ToTypeSig());
			if (DnlibExtensions.IsValueType(type))
				return new ByRefSig(type);
			else
				return type;
		}
        List <ILNode> ConvertToAst(List <ByteCode> body)
        {
            List <ILNode> ast = new List <ILNode>();

            // Convert stack-based IL code to ILAst tree
            foreach (ByteCode byteCode in body)
            {
                ILRange ilRange = new ILRange()
                {
                    From = byteCode.Offset, To = byteCode.EndOffset
                };

                if (byteCode.StackBefore == null)
                {
                    // Unreachable code
                    continue;
                }

                ILExpression expr = new ILExpression(byteCode.Code, byteCode.Operand);
                expr.ILRanges.Add(ilRange);
                if (byteCode.Prefixes != null && byteCode.Prefixes.Length > 0)
                {
                    ILExpressionPrefix[] prefixes = new ILExpressionPrefix[byteCode.Prefixes.Length];
                    for (int i = 0; i < prefixes.Length; i++)
                    {
                        prefixes[i] = new ILExpressionPrefix((ILCode)byteCode.Prefixes[i].OpCode.Code, byteCode.Prefixes[i].Operand);
                    }
                    expr.Prefixes = prefixes;
                }

                // Label for this instruction
                if (byteCode.Label != null)
                {
                    ast.Add(byteCode.Label);
                }

                // Reference arguments using temporary variables
                int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count;
                for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++)
                {
                    StackSlot slot = byteCode.StackBefore[i];
                    expr.Arguments.Add(new ILExpression(ILCode.Ldloc, slot.LoadFrom));
                }

                // Store the result to temporary variable(s) if needed
                if (byteCode.StoreTo == null || byteCode.StoreTo.Count == 0)
                {
                    ast.Add(expr);
                }
                else if (byteCode.StoreTo.Count == 1)
                {
                    ast.Add(new ILExpression(ILCode.Stloc, byteCode.StoreTo[0], expr));
                }
                else
                {
                    ILVariable tmpVar = new ILVariable()
                    {
                        Name = "expr_" + byteCode.Offset.ToString("X2"), IsGenerated = true
                    };
                    ast.Add(new ILExpression(ILCode.Stloc, tmpVar, expr));
                    foreach (ILVariable storeTo in byteCode.StoreTo.AsEnumerable().Reverse())
                    {
                        ast.Add(new ILExpression(ILCode.Stloc, storeTo, new ILExpression(ILCode.Ldloc, tmpVar)));
                    }
                }
            }

            return(ast);
        }
        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);
            }
        }
		/// <summary>
		/// Wraps 'type' in a ByReferenceType if it is a value type. If a constrained prefix is specified,
		/// returns the constrained type wrapped in a ByRefSig.
		/// </summary>
		TypeSig MakeRefIfValueType(TypeSig type, ILExpressionPrefix constrainedPrefix)
		{
			if (constrainedPrefix != null)
				return new ByRefSig(((ITypeDefOrRef)constrainedPrefix.Operand).ToTypeSig());
			if (type.IsValueType)
				return new ByRefSig(type);
			else
				return type;
		}