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; }
/// <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; }