未验证 提交 71e6a3be 编写于 作者: C Charles Stoner 提交者: GitHub

Emit conversions between native integers and pointers directly (#47708)

上级 4ae6eb35
......@@ -1917,16 +1917,20 @@ private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol tar
var s0 = source.StrippedType();
var t0 = target.StrippedType();
if (s0.SpecialType != SpecialType.System_UIntPtr &&
s0.SpecialType != SpecialType.System_IntPtr &&
t0.SpecialType != SpecialType.System_UIntPtr &&
t0.SpecialType != SpecialType.System_IntPtr)
TypeSymbol otherType;
if (isIntPtrOrUIntPtr(s0))
{
otherType = t0;
}
else if (isIntPtrOrUIntPtr(t0))
{
otherType = s0;
}
else
{
return false;
}
TypeSymbol otherType = (s0.SpecialType == SpecialType.System_UIntPtr || s0.SpecialType == SpecialType.System_IntPtr) ? t0 : s0;
if (otherType.IsPointerOrFunctionPointer())
{
return true;
......@@ -1955,6 +1959,9 @@ private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol tar
}
return false;
static bool isIntPtrOrUIntPtr(TypeSymbol type) =>
(type.SpecialType == SpecialType.System_IntPtr || type.SpecialType == SpecialType.System_UIntPtr) && !type.IsNativeIntegerType;
}
private static bool HasExplicitEnumerationConversion(TypeSymbol source, TypeSymbol destination)
......@@ -3494,20 +3501,7 @@ private static bool HasPointerToIntegerConversion(TypeSymbol source, TypeSymbol
// The spec should state that any pointer type is convertible to
// sbyte, byte, ... etc, or any corresponding nullable type.
switch (destination.StrippedType().SpecialType)
{
case SpecialType.System_SByte:
case SpecialType.System_Byte:
case SpecialType.System_Int16:
case SpecialType.System_UInt16:
case SpecialType.System_Int32:
case SpecialType.System_UInt32:
case SpecialType.System_Int64:
case SpecialType.System_UInt64:
return true;
}
return false;
return IsIntegerTypeSupportingPointerConversions(destination.StrippedType());
}
private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol destination)
......@@ -3521,8 +3515,12 @@ private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol
}
// Note that void* is convertible to int?, but int? is not convertible to void*.
return IsIntegerTypeSupportingPointerConversions(source);
}
switch (source.SpecialType)
private static bool IsIntegerTypeSupportingPointerConversions(TypeSymbol type)
{
switch (type.SpecialType)
{
case SpecialType.System_SByte:
case SpecialType.System_Byte:
......@@ -3533,6 +3531,9 @@ private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol
case SpecialType.System_Int64:
case SpecialType.System_UInt64:
return true;
case SpecialType.System_IntPtr:
case SpecialType.System_UIntPtr:
return type.IsNativeIntegerType;
}
return false;
......
......@@ -143,8 +143,8 @@ private void EmitConversion(BoundConversion conversion)
#if DEBUG
switch (fromPredefTypeKind)
{
case Microsoft.Cci.PrimitiveTypeCode.IntPtr:
case Microsoft.Cci.PrimitiveTypeCode.UIntPtr:
case Microsoft.Cci.PrimitiveTypeCode.IntPtr when !fromType.IsNativeIntegerType:
case Microsoft.Cci.PrimitiveTypeCode.UIntPtr when !fromType.IsNativeIntegerType:
case Microsoft.Cci.PrimitiveTypeCode.Pointer:
case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer:
Debug.Assert(IsNumeric(toType));
......@@ -152,8 +152,7 @@ private void EmitConversion(BoundConversion conversion)
default:
Debug.Assert(IsNumeric(fromType));
Debug.Assert(
toPredefTypeKind == Microsoft.Cci.PrimitiveTypeCode.IntPtr ||
toPredefTypeKind == Microsoft.Cci.PrimitiveTypeCode.UIntPtr ||
(toPredefTypeKind == Microsoft.Cci.PrimitiveTypeCode.IntPtr || toPredefTypeKind == Microsoft.Cci.PrimitiveTypeCode.UIntPtr) && !toType.IsNativeIntegerType ||
toPredefTypeKind == Microsoft.Cci.PrimitiveTypeCode.Pointer ||
toPredefTypeKind == Microsoft.Cci.PrimitiveTypeCode.FunctionPointer);
break;
......
......@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
......@@ -6963,16 +6962,8 @@ .maxstack 1
IL_0006: ret
}");
conversions(sourceType: "string", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nint", expectedImplicitIL: null,
// https://github.com/dotnet/roslyn/issues/42457: Investigate whether this conversion (and other
// conversions to/from void*) can use conv.i or conv.u instead of explicit operators on System.[U]IntPtr.
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""System.IntPtr System.IntPtr.op_Explicit(void*)""
IL_0006: ret
}");
conversions(sourceType: "void*", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un"));
conversions(sourceType: "delegate*<void>", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un"));
conversions(sourceType: "bool", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nint", expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u"));
conversions(sourceType: "sbyte", destType: "nint", expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i"));
......@@ -7066,12 +7057,35 @@ .maxstack 1
conversions(sourceType: "string", destType: "nint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nint?", expectedImplicitIL: null,
@"{
// Code size 12 (0xc)
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""System.IntPtr System.IntPtr.op_Explicit(void*)""
IL_0006: newobj ""nint?..ctor(nint)""
IL_000b: ret
IL_0001: newobj ""nint?..ctor(nint)""
IL_0006: ret
}",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldarg.0
IL_0001: conv.ovf.i.un
IL_0002: newobj ""nint?..ctor(nint)""
IL_0007: ret
}");
conversions(sourceType: "delegate*<void>", destType: "nint?", expectedImplicitIL: null,
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: newobj ""nint?..ctor(nint)""
IL_0006: ret
}",
@"{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldarg.0
IL_0001: conv.ovf.i.un
IL_0002: newobj ""nint?..ctor(nint)""
IL_0007: ret
}");
conversions(sourceType: "bool", destType: "nint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nint?", expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint"));
......@@ -7211,14 +7225,8 @@ .maxstack 1
IL_0006: ret
}");
conversions(sourceType: "nint", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint", destType: "void*", expectedImplicitIL: null,
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""void* System.IntPtr.op_Explicit(System.IntPtr)""
IL_0006: ret
}");
conversions(sourceType: "nint", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u"));
conversions(sourceType: "nint", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.u"));
conversions(sourceType: "nint", destType: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint", destType: "char", expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2"));
conversions(sourceType: "nint", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1"));
......@@ -7315,15 +7323,8 @@ .maxstack 1
IL_0006: ret
}");
conversions(sourceType: "nint?", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint?", destType: "void*", expectedImplicitIL: null,
@"{
// Code size 13 (0xd)
.maxstack 1
IL_0000: ldarga.s V_0
IL_0002: call ""nint nint?.Value.get""
IL_0007: call ""void* System.IntPtr.op_Explicit(System.IntPtr)""
IL_000c: ret
}");
conversions(sourceType: "nint?", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint?", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint?", destType: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint?", destType: "char", expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2", "nint"));
conversions(sourceType: "nint?", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1", "nint"));
......@@ -7421,14 +7422,8 @@ .maxstack 1
IL_0006: ret
}");
conversions(sourceType: "string", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nuint", expectedImplicitIL: null,
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""System.UIntPtr System.UIntPtr.op_Explicit(void*)""
IL_0006: ret
}");
conversions(sourceType: "void*", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: convNone);
conversions(sourceType: "delegate*<void>", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: convNone);
conversions(sourceType: "bool", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nuint", expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u"));
conversions(sourceType: "sbyte", destType: "nuint", expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u"));
......@@ -7522,12 +7517,19 @@ .maxstack 1
conversions(sourceType: "string", destType: "nuint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nuint?", expectedImplicitIL: null,
@"{
// Code size 12 (0xc)
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""System.UIntPtr System.UIntPtr.op_Explicit(void*)""
IL_0006: newobj ""nuint?..ctor(nuint)""
IL_000b: ret
IL_0001: newobj ""nuint?..ctor(nuint)""
IL_0006: ret
}");
conversions(sourceType: "delegate*<void>", destType: "nuint?", expectedImplicitIL: null,
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: newobj ""nuint?..ctor(nuint)""
IL_0006: ret
}");
conversions(sourceType: "bool", destType: "nuint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nuint?", expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint"));
......@@ -7667,14 +7669,8 @@ .maxstack 1
IL_0006: ret
}");
conversions(sourceType: "nuint", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint", destType: "void*", expectedImplicitIL: null,
@"{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""void* System.UIntPtr.op_Explicit(System.UIntPtr)""
IL_0006: ret
}");
conversions(sourceType: "nuint", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: convNone);
conversions(sourceType: "nuint", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: convNone);
conversions(sourceType: "nuint", destType: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint", destType: "char", expectedImplicitIL: null, expectedExplicitIL: conv("conv.u2"), expectedCheckedIL: conv("conv.ovf.u2.un"));
conversions(sourceType: "nuint", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1.un"));
......@@ -7769,15 +7765,8 @@ .maxstack 1
IL_0006: ret
}");
conversions(sourceType: "nuint?", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint?", destType: "void*", expectedImplicitIL: null,
@"{
// Code size 13 (0xd)
.maxstack 1
IL_0000: ldarga.s V_0
IL_0002: call ""nuint nuint?.Value.get""
IL_0007: call ""void* System.UIntPtr.op_Explicit(System.UIntPtr)""
IL_000c: ret
}");
conversions(sourceType: "nuint?", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint?", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint?", destType: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint?", destType: "char", expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.u2", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.u2.un", "nuint"));
conversions(sourceType: "nuint?", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nuint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1.un", "nuint"));
......@@ -7883,6 +7872,7 @@ .maxstack 1
}");
conversions(sourceType: "System.IntPtr", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "System.IntPtr", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("void* System.IntPtr.op_Explicit(System.IntPtr)"));
conversions(sourceType: "System.IntPtr", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("void* System.IntPtr.op_Explicit(System.IntPtr)"));
conversions(sourceType: "System.IntPtr", destType: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "System.IntPtr", destType: "char", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("int System.IntPtr.op_Explicit(System.IntPtr)", "conv.u2"), expectedCheckedIL: convAndExplicit("int System.IntPtr.op_Explicit(System.IntPtr)", "conv.ovf.u2"));
conversions(sourceType: "System.IntPtr", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("int System.IntPtr.op_Explicit(System.IntPtr)", "conv.i1"), expectedCheckedIL: convAndExplicit("int System.IntPtr.op_Explicit(System.IntPtr)", "conv.ovf.i1"));
......@@ -8020,6 +8010,7 @@ .maxstack 1
}");
conversions(sourceType: "string", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.IntPtr System.IntPtr.op_Explicit(void*)"));
conversions(sourceType: "delegate*<void>", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.IntPtr System.IntPtr.op_Explicit(void*)"));
conversions(sourceType: "bool", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.IntPtr System.IntPtr.op_Explicit(int)"));
conversions(sourceType: "sbyte", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.IntPtr System.IntPtr.op_Explicit(int)"));
......@@ -8135,6 +8126,7 @@ .maxstack 1
}");
conversions(sourceType: "System.UIntPtr", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "System.UIntPtr", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("void* System.UIntPtr.op_Explicit(System.UIntPtr)"));
conversions(sourceType: "System.UIntPtr", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("void* System.UIntPtr.op_Explicit(System.UIntPtr)"));
conversions(sourceType: "System.UIntPtr", destType: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "System.UIntPtr", destType: "char", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("uint System.UIntPtr.op_Explicit(System.UIntPtr)", "conv.u2"), expectedCheckedIL: convAndExplicit("uint System.UIntPtr.op_Explicit(System.UIntPtr)", "conv.ovf.u2.un"));
conversions(sourceType: "System.UIntPtr", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: convAndExplicit("uint System.UIntPtr.op_Explicit(System.UIntPtr)", "conv.i1"), expectedCheckedIL: convAndExplicit("uint System.UIntPtr.op_Explicit(System.UIntPtr)", "conv.ovf.i1.un"));
......@@ -8330,6 +8322,7 @@ .maxstack 1
}");
conversions(sourceType: "string", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.UIntPtr System.UIntPtr.op_Explicit(void*)"));
conversions(sourceType: "delegate*<void>", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.UIntPtr System.UIntPtr.op_Explicit(void*)"));
conversions(sourceType: "bool", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.UIntPtr System.UIntPtr.op_Explicit(uint)"));
conversions(sourceType: "sbyte", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.UIntPtr System.UIntPtr.op_Explicit(ulong)", "conv.i8"), expectedCheckedIL: explicitAndConv("System.UIntPtr System.UIntPtr.op_Explicit(ulong)", "conv.ovf.u8"));
......@@ -8481,7 +8474,7 @@ .maxstack 1
verifier.VerifyIL("Program.Convert", expectedIL);
}
static bool useUnsafe(string type) => type == "void*";
static bool useUnsafe(string type) => type == "void*" || type == "delegate*<void>";
}
}
......@@ -12243,5 +12236,142 @@ static object Execute(Func<object> f)
0
{(IntPtr.Size == 4 ? "System.OverflowException" : "0")}");
}
[WorkItem(44810, "https://github.com/dotnet/roslyn/issues/44810")]
[Theory]
[InlineData("void*")]
[InlineData("byte*")]
[InlineData("delegate*<void>")]
public void PointerConversions(string pointerType)
{
string source =
$@"using System;
unsafe class Program
{{
static {pointerType} ToPointer1(nint i) => ({pointerType})i;
static {pointerType} ToPointer2(nuint u) => ({pointerType})u;
static {pointerType} ToPointer3(nint i) => checked(({pointerType})i);
static {pointerType} ToPointer4(nuint u) => checked(({pointerType})u);
static nint FromPointer1({pointerType} p) => (nint)p;
static nuint FromPointer2({pointerType} p) => (nuint)p;
static nint FromPointer3({pointerType} p) => checked((nint)p);
static nuint FromPointer4({pointerType} p) => checked((nuint)p);
static object Execute(Func<object> f)
{{
try
{{
return f();
}}
catch (Exception e)
{{
return e.GetType().FullName;
}}
}}
static void Execute({pointerType} p)
{{
Console.WriteLine((int)p);
Console.WriteLine(Execute(() => FromPointer1(p)));
Console.WriteLine(Execute(() => FromPointer2(p)));
Console.WriteLine(Execute(() => FromPointer3(p)));
Console.WriteLine(Execute(() => FromPointer4(p)));
}}
static void Main()
{{
Execute(ToPointer1(-42));
Execute(ToPointer2(42));
Execute(ToPointer1(int.MinValue));
Execute(ToPointer2(uint.MaxValue));
Console.WriteLine(Execute(() => (ulong)ToPointer3(-42)));
Console.WriteLine(Execute(() => (ulong)ToPointer4(42)));
Console.WriteLine(Execute(() => (ulong)ToPointer3(int.MinValue)));
Console.WriteLine(Execute(() => (ulong)ToPointer4(uint.MaxValue)));
}}
}}";
var comp = CreateCompilation(source, options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular9);
string expectedOutput =
$@"-42
-42
{(IntPtr.Size == 4 ? "4294967254" : "18446744073709551574")}
System.OverflowException
{(IntPtr.Size == 4 ? "4294967254" : "18446744073709551574")}
42
42
42
42
42
-2147483648
-2147483648
{(IntPtr.Size == 4 ? "2147483648" : "18446744071562067968")}
System.OverflowException
{(IntPtr.Size == 4 ? "2147483648" : "18446744071562067968")}
-1
{(IntPtr.Size == 4 ? "-1" : "4294967295")}
4294967295
{(IntPtr.Size == 4 ? "System.OverflowException" : "4294967295")}
4294967295
System.OverflowException
42
System.OverflowException
4294967295";
var verifier = CompileAndVerify(comp, verify: Verification.Skipped, expectedOutput: expectedOutput);
verifier.VerifyIL("Program.ToPointer1",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
verifier.VerifyIL("Program.ToPointer2",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
verifier.VerifyIL("Program.ToPointer3",
@"{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldarg.0
IL_0001: conv.ovf.u
IL_0002: ret
}");
verifier.VerifyIL("Program.ToPointer4",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
verifier.VerifyIL("Program.FromPointer1",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
verifier.VerifyIL("Program.FromPointer2",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
verifier.VerifyIL("Program.FromPointer3",
@"{
// Code size 3 (0x3)
.maxstack 1
IL_0000: ldarg.0
IL_0001: conv.ovf.i.un
IL_0002: ret
}");
verifier.VerifyIL("Program.FromPointer4",
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ret
}");
}
}
}
......@@ -7,7 +7,6 @@
using System;
using System.Diagnostics;
using System.Reflection.Metadata;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeGen
......@@ -151,6 +150,11 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
// 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);
......@@ -164,6 +168,8 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
switch (fromPredefTypeKind)
{
case Microsoft.Cci.PrimitiveTypeCode.UIntPtr:
case Microsoft.Cci.PrimitiveTypeCode.Pointer:
case Microsoft.Cci.PrimitiveTypeCode.FunctionPointer:
break; // NOP
case Microsoft.Cci.PrimitiveTypeCode.UInt8:
case Microsoft.Cci.PrimitiveTypeCode.UInt16:
......@@ -306,6 +312,11 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
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);
}
......@@ -328,6 +339,9 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
// 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);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册