| File: CodeGen\ILBuilderConversions.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Diagnostics; using System.Reflection.Metadata; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CodeGen { internal partial class ILBuilder { public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefTypeKind, Microsoft.Cci.PrimitiveTypeCode toPredefTypeKind, bool @checked) { bool fromUnsigned = fromPredefTypeKind.IsUnsigned(); switch (toPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.Int8: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.Int8: break; // NOP default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_i1_un : ILOpCode.Conv_ovf_i1); else this.EmitOpCode(ILOpCode.Conv_i1); break; } break; case Microsoft.Cci.PrimitiveTypeCode.UInt8: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt8: break; // NOP default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_u1_un : ILOpCode.Conv_ovf_u1); else this.EmitOpCode(ILOpCode.Conv_u1); break; } break; case Microsoft.Cci.PrimitiveTypeCode.Int16: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.Int16: break; // NOP default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_i2_un : ILOpCode.Conv_ovf_i2); else this.EmitOpCode(ILOpCode.Conv_i2); break; } break; case Microsoft.Cci.PrimitiveTypeCode.Char: case Microsoft.Cci.PrimitiveTypeCode.UInt16: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.Char: break; // NOP default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_u2_un : ILOpCode.Conv_ovf_u2); else this.EmitOpCode(ILOpCode.Conv_u2); break; } break; case Microsoft.Cci.PrimitiveTypeCode.Int32: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.Int32: case Microsoft.Cci.PrimitiveTypeCode.Char: break; // NOP case Microsoft.Cci.PrimitiveTypeCode.UInt32: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_i4_un); break; // NOP in unchecked default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_i4_un : ILOpCode.Conv_ovf_i4); else this.EmitOpCode(ILOpCode.Conv_i4); break; } break; case Microsoft.Cci.PrimitiveTypeCode.UInt32: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.Char: break; // NOP case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_u4); break; // NOP in unchecked default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_u4_un : ILOpCode.Conv_ovf_u4); else this.EmitOpCode(ILOpCode.Conv_u4); break; } break; case Microsoft.Cci.PrimitiveTypeCode.IntPtr: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.IntPtr: case Microsoft.Cci.PrimitiveTypeCode.UIntPtr when !@checked: break; // NOP case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: this.EmitOpCode(ILOpCode.Conv_i); // potentially widening, so not NOP break; case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.Char: // Doesn't actually matter whether we sign extend, because // bit 32 can't be set in any of these types. this.EmitOpCode(ILOpCode.Conv_u); // potentially widening, so not NOP break; case Microsoft.Cci.PrimitiveTypeCode.UInt32: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_i_un); else // Don't want to sign extend if this is a widening conversion. this.EmitOpCode(ILOpCode.Conv_u); // potentially widening, so not NOP break; case Microsoft.Cci.PrimitiveTypeCode.Pointer: case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer: if (@checked) goto default; break; // NOP default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_i_un : ILOpCode.Conv_ovf_i); else this.EmitOpCode(ILOpCode.Conv_i); break; } break; case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: case Microsoft.Cci.PrimitiveTypeCode.IntPtr when !@checked: case Microsoft.Cci.PrimitiveTypeCode.Pointer: case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer: break; // NOP case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.Char: this.EmitOpCode(ILOpCode.Conv_u); // potentially widening, so not NOP break; case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_u); else this.EmitOpCode(ILOpCode.Conv_i); // potentially widening, so not NOP break; default: if (@checked) this.EmitOpCode(fromUnsigned ? ILOpCode.Conv_ovf_u_un : ILOpCode.Conv_ovf_u); else this.EmitOpCode(ILOpCode.Conv_u); break; } break; case Microsoft.Cci.PrimitiveTypeCode.Int64: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.Int64: break; //NOP case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: case Microsoft.Cci.PrimitiveTypeCode.IntPtr: this.EmitOpCode(ILOpCode.Conv_i8); // sign extend break; case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.Char: this.EmitOpCode(ILOpCode.Conv_u8); // 0 extend break; case Microsoft.Cci.PrimitiveTypeCode.Pointer: case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer: case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_i8_un); else this.EmitOpCode(ILOpCode.Conv_u8); // 0 extend if unchecked break; case Microsoft.Cci.PrimitiveTypeCode.UInt64: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_i8_un); break; // NOP in unchecked default: Debug.Assert(fromPredefTypeKind.IsFloatingPoint()); if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_i8); else this.EmitOpCode(ILOpCode.Conv_i8); break; } break; case Microsoft.Cci.PrimitiveTypeCode.UInt64: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt64: break; //NOP case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.Pointer: case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer: case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: case Microsoft.Cci.PrimitiveTypeCode.Char: this.EmitOpCode(ILOpCode.Conv_u8); // 0 extend break; case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: case Microsoft.Cci.PrimitiveTypeCode.IntPtr: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_u8); else this.EmitOpCode(ILOpCode.Conv_i8); // sign extend if unchecked break; case Microsoft.Cci.PrimitiveTypeCode.Int64: if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_u8); break; // NOP in unchecked default: Debug.Assert(fromPredefTypeKind.IsFloatingPoint()); if (@checked) this.EmitOpCode(ILOpCode.Conv_ovf_u8); else this.EmitOpCode(ILOpCode.Conv_u8); break; } break; case Microsoft.Cci.PrimitiveTypeCode.Float32: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.UInt64: case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: this.EmitOpCode(ILOpCode.Conv_r_un); break; } this.EmitOpCode(ILOpCode.Conv_r4); break; case Microsoft.Cci.PrimitiveTypeCode.Float64: switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.UInt64: case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: this.EmitOpCode(ILOpCode.Conv_r_un); break; } this.EmitOpCode(ILOpCode.Conv_r8); break; case Microsoft.Cci.PrimitiveTypeCode.Pointer: case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer: if (@checked) { switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.UInt32: this.EmitOpCode(ILOpCode.Conv_u); break; case Microsoft.Cci.PrimitiveTypeCode.UInt64: this.EmitOpCode(ILOpCode.Conv_ovf_u_un); break; case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: case Microsoft.Cci.PrimitiveTypeCode.Int64: this.EmitOpCode(ILOpCode.Conv_ovf_u); break; case Microsoft.Cci.PrimitiveTypeCode.IntPtr: this.EmitOpCode(ILOpCode.Conv_ovf_u); break; case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: break; // NOP default: throw ExceptionUtilities.UnexpectedValue(fromPredefTypeKind); } } else { switch (fromPredefTypeKind) { case Microsoft.Cci.PrimitiveTypeCode.UInt8: case Microsoft.Cci.PrimitiveTypeCode.UInt16: case Microsoft.Cci.PrimitiveTypeCode.UInt32: case Microsoft.Cci.PrimitiveTypeCode.UInt64: case Microsoft.Cci.PrimitiveTypeCode.Int64: this.EmitOpCode(ILOpCode.Conv_u); break; case Microsoft.Cci.PrimitiveTypeCode.Int8: case Microsoft.Cci.PrimitiveTypeCode.Int16: case Microsoft.Cci.PrimitiveTypeCode.Int32: // This matches dev10. Presumably, we're using conv_i, // rather than conv_u, to sign-extend the value. this.EmitOpCode(ILOpCode.Conv_i); break; case Microsoft.Cci.PrimitiveTypeCode.IntPtr: case Microsoft.Cci.PrimitiveTypeCode.UIntPtr: break; // NOP default: throw ExceptionUtilities.UnexpectedValue(fromPredefTypeKind); } } break; default: throw ExceptionUtilities.UnexpectedValue(toPredefTypeKind); } } } }