private bool ConvertRefTypeToValueType(CilExpression argument) { if (argument.ExpressionType.IsTypeOf("System", "Object")) { if (argument is CilInstructionExpression e && e.Instructions.Count == 1) { switch (e.Instructions[0].OpCode.Code) { case CilCode.Ldind_Ref: // Load from pointer. LdObj(e); break; case CilCode.Box: // If argument is a box expression, then we can apply an optimisation; remove both // box and unbox, and convert the embedded expression directly: e.Arguments[0].ExpectedType = argument.ExpectedType; argument.ReplaceWith(ConvertValueType(e.Arguments[0]).Remove()); return(true); default: // Argument is something else. We need to unbox. UnboxAny(argument); break; } } else { UnboxAny(argument); } return(true); }
private bool EnsureTypeSafety(CilExpression argument) { bool changed = false; if (!_context.TypeHelper.IsAssignableTo(argument.ExpressionType, argument.ExpectedType)) { if (!argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType) { // Reference type -> Value type. if (argument.ExpressionType.IsTypeOf("System", "Object")) { if (argument is CilInstructionExpression e && e.Instructions.Count == 1 && e.Instructions[0].OpCode.Code == CilCode.Ldind_Ref) { LdObj(e); } else { UnboxAny(argument); } changed = true; } else if (argument.ExpressionType is PointerTypeSignature) { ConvertValueType(argument); changed = true; } } else if (!argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType) { // Reference type -> Reference type. CastClass(argument); changed = true; } else if (argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType) { // Value type -> Reference type. var newArg = Box(argument); if (!newArg.ExpectedType.IsTypeOf("System", "Object")) { CastClass(newArg); } changed = true; } else if (argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType) { // Value type -> Value type. ConvertValueType(argument); changed = true; } }
private bool IsBoxExpression(CilExpression expression, out CilExpression argument, out ITypeDefOrRef boxedType) { if (expression is CilInstructionExpression arg && arg.Instructions.Count == 1 && arg.Instructions[0].OpCode.Code == CilCode.Box) { argument = arg.Arguments[0]; boxedType = (ITypeDefOrRef)arg.Instructions[0].Operand; return(true); } argument = null; boxedType = null; return(false); }
private bool EnsureTypeSafety(CilExpression argument) { bool changed = false; if (!_context.TypeHelper.IsAssignableTo(argument.ExpressionType, argument.ExpectedType)) { if (!argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType) { // Reference type -> Value type. changed = ConvertRefTypeToValueType(argument); } else if (!argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType) { // Reference type -> Reference type. CastClass(argument); changed = true; } else if (argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType) { // Value type -> Reference type. var newArg = Box(argument); if (!newArg.ExpectedType.IsTypeOf("System", "Object")) { CastClass(newArg); } changed = true; } else if (argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType) { // Value type -> Value type. ConvertValueType(argument); changed = true; } } return(changed); }