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, 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, 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 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); }