public override CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { var result = base.Translate(context, expression); result.ExpressionType = null; return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (LdftnAnnotation)expression.Annotation; IMethodDescriptor method; if (!annotation.IsIntraLinked) { method = annotation.Method; } else { method = context.ExportResolver.ResolveMethod(annotation.Function.EntrypointAddress); if (method == null) { throw new RecompilerException( $"Could not resolve function_{annotation.Function.EntrypointAddress:X4} to a physical method."); } } var result = new CilInstructionExpression(CilOpCodes.Ldftn, method) { ExpressionType = context.TargetModule.CorLibTypeFactory.IntPtr }; if (annotation.IsVirtual) { var callingObject = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); result.Instructions[0].OpCode = CilOpCodes.Ldvirtftn; result.Arguments.Add(callingObject); } return(result); }
public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { switch (expression.OpCode.Code) { case ILCode.PUSHR_OBJECT: case ILCode.PUSHR_BYTE: case ILCode.PUSHR_WORD: case ILCode.PUSHR_DWORD: case ILCode.PUSHR_QWORD: return(CompileRegisterPush(context, expression)); case ILCode.PUSHI_DWORD: return(new CilInstructionExpression(CilOpCodes.Ldc_I4, unchecked ((int)(uint)expression.Operand)) { ExpressionType = context.TargetImage.TypeSystem.Int32 }); case ILCode.PUSHI_QWORD: return(new CilInstructionExpression(CilOpCodes.Ldc_I8, unchecked ((long)(ulong)expression.Operand)) { ExpressionType = context.TargetImage.TypeSystem.Int64 }); default: throw new ArgumentOutOfRangeException(); } }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var boxMetadata = (BoxAnnotation)expression.Annotation; switch (boxMetadata.ReturnType) { case VMType.Object: switch (boxMetadata.Value) { case string stringValue: return(new CilInstructionExpression(CilOpCodes.Ldstr, stringValue) { ExpressionType = context.TargetImage.TypeSystem.String }); case null: var argument = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); argument.ExpectedType = boxMetadata.Type; return(new CilInstructionExpression(CilOpCodes.Box, boxMetadata.Type, argument) { ExpressionType = context.TargetImage.TypeSystem.Object, }); default: throw new NotImplementedException(); } case VMType.Byte: case VMType.Word: case VMType.Dword: return(new CilInstructionExpression(CilOpCodes.Ldc_I4, Convert.ToInt32(boxMetadata.Value)) { ExpressionType = context.TargetImage.TypeSystem.Int32, }); case VMType.Qword: return(new CilInstructionExpression(CilOpCodes.Ldc_I8, Convert.ToInt64(boxMetadata.Value)) { ExpressionType = context.TargetImage.TypeSystem.Int64, }); case VMType.Real32: return(new CilInstructionExpression(CilOpCodes.Ldc_R4, Convert.ToSingle(boxMetadata.Value)) { ExpressionType = context.TargetImage.TypeSystem.Single, }); case VMType.Real64: return(new CilInstructionExpression(CilOpCodes.Ldc_R8, Convert.ToDouble(boxMetadata.Value)) { ExpressionType = context.TargetImage.TypeSystem.Double, }); case VMType.Unknown: case VMType.Pointer: default: throw new NotImplementedException(); } }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (LdftnAnnotation)expression.Annotation; ICallableMemberReference method; if (!annotation.IsIntraLinked) { method = annotation.Method; } else { method = context.ExportResolver.ResolveMethod(annotation.Function.EntrypointAddress); if (method == null) { throw new RecompilerException( $"Could not resolve function_{annotation.Function.EntrypointAddress:X4} to a physical method."); } } var result = new CilInstructionExpression(CilOpCodes.Ldftn, method) { ExpressionType = context.TargetImage.TypeSystem.IntPtr }; return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var metadata = (TypeAnnotation)expression.Annotation; return(new CilInstructionExpression(CilOpCodes.Sizeof, metadata.Type) { ExpressionType = context.TargetModule.CorLibTypeFactory.Int32 }); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var argument = (CilExpression)expression.Arguments.Last().AcceptVisitor(context.Recompiler); argument.ExpectedType = context.TargetModule.CorLibTypeFactory.UIntPtr; return(new CilInstructionExpression(CilOpCodes.Localloc, null, argument) { ExpressionType = new PointerTypeSignature(context.TargetModule.CorLibTypeFactory.Byte) }); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (TokenAnnotation)expression.Annotation; var member = annotation.Member; string typeName; switch (member.MetadataToken.Table) { case TableIndex.TypeDef: case TableIndex.TypeRef: case TableIndex.TypeSpec: typeName = nameof(RuntimeTypeHandle); break; case TableIndex.Method: case TableIndex.MethodSpec: typeName = nameof(RuntimeMethodHandle); break; case TableIndex.Field: typeName = nameof(RuntimeFieldHandle); break; case TableIndex.MemberRef: var reference = (MemberReference)member; if (reference.Signature.IsMethod) { typeName = nameof(RuntimeMethodHandle); } else if (reference.Signature.IsField) { typeName = nameof(RuntimeFieldHandle); } else { throw new RecompilerException("Detected a reference to a MemberRef that is not a method or a field."); } break; default: throw new ArgumentOutOfRangeException(); } return(new CilInstructionExpression(CilOpCodes.Ldtoken, annotation.Member) { ExpressionType = new TypeReference( context.TargetModule, context.TargetModule.CorLibTypeFactory.CorLibScope, "System", typeName) }); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var metadata = (FieldAnnotation)expression.Annotation; // Enter generic context for member. context.EnterMember(metadata.Field); var fieldDef = metadata.Field.Resolve(); bool hasThis = !fieldDef?.IsStatic ?? metadata.Field.Signature.HasThis; // Select opcode and expression type. var expressionType = metadata.Field.Signature.FieldType; CilOpCode opCode; if (metadata.IsAddress) { expressionType = new ByReferenceTypeSignature(expressionType); opCode = hasThis ? CilOpCodes.Ldflda : CilOpCodes.Ldsflda; } else { opCode = hasThis ? CilOpCodes.Ldfld : CilOpCodes.Ldsfld; } // Construct CIL expression. var result = new CilInstructionExpression(opCode, metadata.Field) { ExpressionType = expressionType.InstantiateGenericTypes(context.GenericContext) }; if (hasThis) { // Recompile object expression if field is an instance field. var objectExpression = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); var objectType = metadata.Field.DeclaringType .ToTypeSignature() .InstantiateGenericTypes(context.GenericContext); if (metadata.IsAddress) { objectType = new ByReferenceTypeSignature(objectType); } objectExpression.ExpectedType = objectType; result.Arguments.Add(objectExpression); } // Leave generic context. context.ExitMember(); return(result); }
public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { CilOpCode code; switch (expression.OpCode.Code) { case ILCode.SIND_PTR: code = CilOpCodes.Stind_I; break; case ILCode.SIND_BYTE: code = CilOpCodes.Stind_I1; break; case ILCode.SIND_WORD: code = CilOpCodes.Stind_I2; break; case ILCode.SIND_DWORD: code = CilOpCodes.Stind_I4; break; case ILCode.SIND_QWORD: code = CilOpCodes.Stind_I8; break; case ILCode.SIND_OBJECT: code = CilOpCodes.Stind_Ref; break; default: throw new ArgumentOutOfRangeException(nameof(expression)); } var value = (CilExpression)expression.Arguments[0].AcceptVisitor(context.Recompiler); var destination = (CilExpression)expression.Arguments[1].AcceptVisitor(context.Recompiler); switch (destination.ExpressionType) { case PointerTypeSignature pointerType: value.ExpectedType = pointerType.BaseType; break; case ByReferenceTypeSignature byRefType: value.ExpectedType = byRefType.BaseType; break; } return(new CilInstructionExpression(code, null, destination, value) { ExpressionType = null }); }
public virtual bool ApplyTransformation(RecompilerContext context, CilCompilationUnit unit) { bool changed = false; while (unit.AcceptVisitor(this)) { changed = true; // Repeat until no more changes. } return(changed); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var metadata = (CastAnnotation)expression.Annotation; var opCode = metadata.IsSafeCast ? CilOpCodes.Isinst : CilOpCodes.Castclass; var value = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); return(new CilInstructionExpression(opCode, metadata.Type, value) { ExpressionType = metadata.Type }); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (ThrowAnnotation)expression.Annotation; var argument = (CilExpression)expression.Arguments[2].AcceptVisitor(context.Recompiler); argument.ExpectedType = context.ReferenceImporter.ImportType(typeof(Exception)); var result = new CilInstructionExpression(annotation.IsRethrow ? CilOpCodes.Rethrow : CilOpCodes.Throw, null, argument); return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (UnboxAnnotation)expression.Annotation; var value = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); value.ExpectedType = context.TargetImage.TypeSystem.Object; return(new CilUnboxToVmExpression(annotation.Type, value) { ExpressionType = context.TargetImage.TypeSystem.Object }); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (TokenAnnotation)expression.Annotation; var member = annotation.Member; ITypeDescriptor expressionType; switch (member.MetadataToken.TokenType) { case MetadataTokenType.TypeDef: case MetadataTokenType.TypeRef: case MetadataTokenType.TypeSpec: expressionType = context.ReferenceImporter.ImportType(typeof(RuntimeTypeHandle)); break; case MetadataTokenType.Method: case MetadataTokenType.MethodSpec: expressionType = context.ReferenceImporter.ImportType(typeof(RuntimeMethodHandle)); break; case MetadataTokenType.Field: expressionType = context.ReferenceImporter.ImportType(typeof(RuntimeFieldHandle)); break; case MetadataTokenType.MemberRef: var reference = (ICallableMemberReference)member; if (reference.Signature.IsMethod) { expressionType = context.ReferenceImporter.ImportType(typeof(RuntimeMethodHandle)); } else if (reference.Signature.IsField) { expressionType = context.ReferenceImporter.ImportType(typeof(RuntimeFieldHandle)); } else { throw new RecompilerException("Detected a reference to a MemberRef that is not a method or a field."); } break; default: throw new ArgumentOutOfRangeException(); } return(new CilInstructionExpression(CilOpCodes.Ldtoken, annotation.Member) { ExpressionType = expressionType }); }
public virtual CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { if (!SupportedOpCodes.Contains(expression.OpCode.Code)) { throw new NotSupportedException(); } var result = new CilInstructionExpression(); // Copy instructions foreach (var instruction in NewInstructions) { result.Instructions.Add(new CilInstruction(0, instruction.OpCode, instruction.Operand)); } // Create arguments for (var i = 0; i < expression.Arguments.Count; i++) { // Convert argument. var argument = expression.Arguments[i]; var cilArgument = (CilExpression)argument.AcceptVisitor(context.Recompiler); // Check type. cilArgument.ExpectedType = expression.OpCode.StackBehaviourPop .GetArgumentType(i) .ToMetadataType(context.TargetImage); // Convert if necessary, and add to argument list. result.Arguments.Add(cilArgument); } // Determine expression type from opcode. if (expression.OpCode.StackBehaviourPush != ILStackBehaviour.None) { result.ExpressionType = expression.OpCode.StackBehaviourPush .GetResultType() .ToMetadataType(context.TargetImage); } result.ShouldEmitFlagsUpdate = expression.IsFlagDataSource; if (expression.IsFlagDataSource) { result.AffectedFlags = expression.OpCode.AffectedFlags; result.InvertedFlagsUpdate = InvertedFlagsUpdate; } return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var annotation = (TypeAnnotation)expression.Annotation; var argument = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); argument.ExpectedType = new ByReferenceTypeSignature( context.ReferenceImporter.ImportTypeSignature(annotation.Type.ToTypeSignature())); var result = new CilInstructionExpression(CilOpCodes.Initobj, annotation.Type, argument) { ExpressionType = null }; return(result); }
/// <inheritdoc /> public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { // CKOVERFLOW is currently not supported. This is in most cases not a big issue as the extra properties of // the overflow checked instructions are not really used all that often in real world applications. // We therefore just emit a NOP for now. var method = context.MethodBody.Owner; string displayName = method.MetadataToken != 0 ? method.MetadataToken.ToInt32().ToString("X8") : method.Name; context.Logger.Warning(Tag, $"Virtualized method {displayName} contains overflow checks which are not supported by OldRod. Resulting code might be inaccurate."); return(new CilInstructionExpression(CilOpCodes.Nop)); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var metadata = (FieldAnnotation)expression.Annotation; var fieldType = metadata.Field.Signature.FieldType; // Enter generic context. context.EnterMember(metadata.Field); var fieldDef = metadata.Field.Resolve(); bool hasThis = !fieldDef?.IsStatic ?? metadata.Field.Signature.HasThis; // Construct CIL expression. var result = new CilInstructionExpression(hasThis ? CilOpCodes.Stfld : CilOpCodes.Stsfld, metadata.Field); if (hasThis) { // Recompile object expression if field is an instance field. var objectExpression = (CilExpression)expression.Arguments[expression.Arguments.Count - 2] .AcceptVisitor(context.Recompiler); var objectType = metadata.Field.DeclaringType .ToTypeSignature() .InstantiateGenericTypes(context.GenericContext); // Struct members can only be accessed when the object is passed on by reference. if (metadata.Field.DeclaringType.IsValueType) { objectType = new ByReferenceTypeSignature(objectType); } objectExpression.ExpectedType = objectType; result.Arguments.Add(objectExpression); } // Recompile value. var valueExpression = (CilExpression)expression.Arguments[expression.Arguments.Count - 1] .AcceptVisitor(context.Recompiler); valueExpression.ExpectedType = fieldType.InstantiateGenericTypes(context.GenericContext); result.Arguments.Add(valueExpression); // Exit generic context. context.ExitMember(); return(result); }
public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { var callMetadata = (CallAnnotation)expression.Annotation; // Convert entrypoint address to physical method def. var method = context.ExportResolver.ResolveMethod(callMetadata.Function.EntrypointAddress); var methodSig = ((MethodSignature)method.Signature); // Create call instruction. CilExpression result = new CilInstructionExpression(CilOpCodes.Call, method, context.RecompileCallArguments(method, expression.Arguments.Skip(1).ToArray(), VMECallOpCode.CALL)) { ExpressionType = methodSig.ReturnType }; // Make sure the resulting object is converted to an unsigned integer if necessary. return(result); }
public override bool ApplyTransformation(RecompilerContext context, CilCompilationUnit unit) { _context = context; return(base.ApplyTransformation(context, unit)); }
public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { var arguments = expression.Arguments .Select(a => (CilExpression)a.AcceptVisitor(context.Recompiler)) .ToArray(); CilOpCode opCode; switch (expression.OpCode.Code) { case ILCode.__EQUALS_OBJECT: opCode = CilOpCodes.Ceq; break; case ILCode.__EQUALS_R32: case ILCode.__EQUALS_R64: case ILCode.__EQUALS_DWORD: case ILCode.__EQUALS_QWORD: opCode = CilOpCodes.Ceq; break; case ILCode.__GT_R32: case ILCode.__GT_R64: opCode = CilOpCodes.Cgt; break; case ILCode.__GT_DWORD: case ILCode.__GT_QWORD: opCode = CilOpCodes.Cgt_Un; break; case ILCode.__LT_R32: case ILCode.__LT_R64: opCode = CilOpCodes.Clt; break; case ILCode.__LT_DWORD: case ILCode.__LT_QWORD: opCode = CilOpCodes.Clt_Un; break; default: throw new ArgumentOutOfRangeException(nameof(expression)); } var argumentType = expression.OpCode.StackBehaviourPop.GetArgumentType(0) .ToMetadataType(context.TargetModule) .ToTypeSignature(); var result = new CilInstructionExpression(opCode) { ExpressionType = context.TargetModule.CorLibTypeFactory.Boolean }; foreach (var argument in arguments) { argument.ExpectedType = argumentType; result.Arguments.Add(argument); } return(result); }
private static CilExpression CompileRegisterPush(RecompilerContext context, ILInstructionExpression expression) { var cilExpression = (CilExpression)expression.Arguments[0].AcceptVisitor(context.Recompiler); var resultType = expression.OpCode.StackBehaviourPush.GetResultType(); if (cilExpression is CilUnboxToVmExpression) { // HACK: Unbox expressions unbox the value from the stack, but also convert it to their unsigned // variant and box it again into an object. We need to unpack it again, however, we do not // know the actual type of the value inside the box, as this is determined at runtime. // // For now, we just make use of the Convert class provided by .NET, which works but would rather // see a true "native" CIL conversion instead. MethodBase convertMethod; switch (resultType) { case VMType.Byte: convertMethod = typeof(Convert).GetMethod("ToByte", new[] { typeof(object) }); break; case VMType.Word: convertMethod = typeof(Convert).GetMethod("ToUInt16", new[] { typeof(object) }); break; case VMType.Dword: convertMethod = typeof(Convert).GetMethod("ToUInt32", new[] { typeof(object) }); break; case VMType.Qword: convertMethod = typeof(Convert).GetMethod("ToUInt64", new[] { typeof(object) }); break; default: throw new ArgumentOutOfRangeException(); } cilExpression.ExpectedType = context.TargetImage.TypeSystem.Object; cilExpression = new CilInstructionExpression( CilOpCodes.Call, context.ReferenceImporter.ImportMethod(convertMethod), cilExpression); } if (resultType == VMType.Object) { if (cilExpression.ExpressionType.IsValueType) { if (cilExpression is CilInstructionExpression instructionExpression && instructionExpression.Instructions.Count == 1 && instructionExpression.Instructions[0].IsLdcI4 && instructionExpression.Instructions[0].GetLdcValue() == 0) { cilExpression = new CilInstructionExpression(CilOpCodes.Ldnull); } else { // If expression returns a value type, we have to box it to an object. cilExpression = new CilInstructionExpression(CilOpCodes.Box, context.ReferenceImporter.ImportType(cilExpression.ExpressionType.ToTypeDefOrRef()), cilExpression); } } else { // Use the reference type of the expression instead of System.Object. cilExpression.ExpressionType = cilExpression.ExpressionType; } }
public void ApplyTransformation(RecompilerContext context, CilCompilationUnit unit) { _context = context; VisitCompilationUnit(unit); }
public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { return(new CilInstructionExpression(CilOpCodes.Nop)); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var ecall = (ECallAnnotation)expression.Annotation; var methodSig = ecall.Method.Signature; // Select calling instruction, return type and call prefix. CilInstruction prefix = null; TypeSignature resultType; CilOpCode opcode; object operand = ecall.Method; switch (ecall.OpCode) { case VMECallOpCode.CALL: opcode = CilOpCodes.Call; resultType = methodSig.ReturnType; break; case VMECallOpCode.CALLVIRT: opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; case VMECallOpCode.NEWOBJ: opcode = CilOpCodes.Newobj; resultType = ecall.Method.DeclaringType.ToTypeSignature(); // KoiVM translates "newarr ElementType" instructions to "newobj ElementType[]::.ctor(int32)". // Revert this operation if necessary: if (resultType is SzArrayTypeSignature arrayType) { opcode = CilOpCodes.Newarr; operand = context.ReferenceImporter.ImportType(arrayType.BaseType.ToTypeDefOrRef()); } break; case VMECallOpCode.CALLVIRT_CONSTRAINED: prefix = new CilInstruction(CilOpCodes.Constrained, ecall.ConstrainedType); opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; default: throw new ArgumentOutOfRangeException(); } // Enter generic context of method. context.EnterMember(ecall.Method); // Collect arguments. var arguments = expression.Arguments .Skip(ecall.IsConstrained ? 3 : 2) .ToArray(); // Build call expression. var result = new CilInstructionExpression(opcode, operand, context.RecompileCallArguments(ecall.Method, arguments, ecall.OpCode, ecall.ConstrainedType)) { ExpressionType = resultType.InstantiateGenericTypes(context.GenericContext) }; // Add prefix when necessary. if (prefix != null) { result.Instructions.Insert(0, prefix); } // Leave generic context. context.ExitMember(); return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var ecall = (ECallAnnotation)expression.Annotation; var methodSig = (MethodSignature)ecall.Method.Signature; // Select calling instruction, return type and call prefix. CilInstruction prefix = null; TypeSignature resultType; CilOpCode opcode; switch (ecall.OpCode) { case VMECallOpCode.CALL: opcode = CilOpCodes.Call; resultType = methodSig.ReturnType; break; case VMECallOpCode.CALLVIRT: opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; case VMECallOpCode.NEWOBJ: opcode = CilOpCodes.Newobj; resultType = ecall.Method.DeclaringType.ToTypeSignature(); break; case VMECallOpCode.CALLVIRT_CONSTRAINED: prefix = CilInstruction.Create(CilOpCodes.Constrained, ecall.ConstrainedType); opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; default: throw new ArgumentOutOfRangeException(); } // Enter generic context of method. context.EnterMember(ecall.Method); // Collect arguments. var arguments = expression.Arguments .Skip(ecall.IsConstrained ? 3 : 2) .ToArray(); // Build call expression. var result = new CilInstructionExpression(opcode, ecall.Method, context.RecompileCallArguments(ecall.Method, arguments, ecall.OpCode == VMECallOpCode.NEWOBJ)) { ExpressionType = resultType.InstantiateGenericTypes(context.GenericContext) }; // Add prefix when necessary. if (prefix != null) { result.Arguments[0].ExpectedType = ecall.ConstrainedType; result.Instructions.Insert(0, prefix); } // Leave generic context. context.ExitMember(); return(result); }
public override bool ApplyTransformation(RecompilerContext context, CilCompilationUnit unit) { _context = context; _helper = new TypeHelper(context.ReferenceImporter); return(base.ApplyTransformation(context, unit)); }
void ICilAstTransform.ApplyTransformation(RecompilerContext context, CilCompilationUnit unit) { ApplyTransformation(context, unit); }