Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
71e6a3be
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
71e6a3be
编写于
9月 16, 2020
作者:
C
Charles Stoner
提交者:
GitHub
9月 16, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Emit conversions between native integers and pointers directly (#47708)
上级
4ae6eb35
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
232 addition
and
88 deletion
+232
-88
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
.../Portable/Binder/Semantics/Conversions/ConversionsBase.cs
+22
-21
src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs
src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs
+3
-4
src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs
...lers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs
+192
-62
src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs
src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs
+15
-1
未找到文件。
src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs
浏览文件 @
71e6a3be
...
@@ -1917,16 +1917,20 @@ private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol tar
...
@@ -1917,16 +1917,20 @@ private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol tar
var
s0
=
source
.
StrippedType
();
var
s0
=
source
.
StrippedType
();
var
t0
=
target
.
StrippedType
();
var
t0
=
target
.
StrippedType
();
if
(
s0
.
SpecialType
!=
SpecialType
.
System_UIntPtr
&&
TypeSymbol
otherType
;
s0
.
SpecialType
!=
SpecialType
.
System_IntPtr
&&
if
(
isIntPtrOrUIntPtr
(
s0
))
t0
.
SpecialType
!=
SpecialType
.
System_UIntPtr
&&
{
t0
.
SpecialType
!=
SpecialType
.
System_IntPtr
)
otherType
=
t0
;
}
else
if
(
isIntPtrOrUIntPtr
(
t0
))
{
otherType
=
s0
;
}
else
{
{
return
false
;
return
false
;
}
}
TypeSymbol
otherType
=
(
s0
.
SpecialType
==
SpecialType
.
System_UIntPtr
||
s0
.
SpecialType
==
SpecialType
.
System_IntPtr
)
?
t0
:
s0
;
if
(
otherType
.
IsPointerOrFunctionPointer
())
if
(
otherType
.
IsPointerOrFunctionPointer
())
{
{
return
true
;
return
true
;
...
@@ -1955,6 +1959,9 @@ private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol tar
...
@@ -1955,6 +1959,9 @@ private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol tar
}
}
return
false
;
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
)
private
static
bool
HasExplicitEnumerationConversion
(
TypeSymbol
source
,
TypeSymbol
destination
)
...
@@ -3494,20 +3501,7 @@ private static bool HasPointerToIntegerConversion(TypeSymbol source, TypeSymbol
...
@@ -3494,20 +3501,7 @@ private static bool HasPointerToIntegerConversion(TypeSymbol source, TypeSymbol
// The spec should state that any pointer type is convertible to
// The spec should state that any pointer type is convertible to
// sbyte, byte, ... etc, or any corresponding nullable type.
// sbyte, byte, ... etc, or any corresponding nullable type.
switch
(
destination
.
StrippedType
().
SpecialType
)
return
IsIntegerTypeSupportingPointerConversions
(
destination
.
StrippedType
());
{
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
;
}
}
private
static
bool
HasIntegerToPointerConversion
(
TypeSymbol
source
,
TypeSymbol
destination
)
private
static
bool
HasIntegerToPointerConversion
(
TypeSymbol
source
,
TypeSymbol
destination
)
...
@@ -3521,8 +3515,12 @@ private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol
...
@@ -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*.
// 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_SByte
:
case
SpecialType
.
System_Byte
:
case
SpecialType
.
System_Byte
:
...
@@ -3533,6 +3531,9 @@ private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol
...
@@ -3533,6 +3531,9 @@ private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol
case
SpecialType
.
System_Int64
:
case
SpecialType
.
System_Int64
:
case
SpecialType
.
System_UInt64
:
case
SpecialType
.
System_UInt64
:
return
true
;
return
true
;
case
SpecialType
.
System_IntPtr
:
case
SpecialType
.
System_UIntPtr
:
return
type
.
IsNativeIntegerType
;
}
}
return
false
;
return
false
;
...
...
src/Compilers/CSharp/Portable/CodeGen/EmitConversion.cs
浏览文件 @
71e6a3be
...
@@ -143,8 +143,8 @@ private void EmitConversion(BoundConversion conversion)
...
@@ -143,8 +143,8 @@ private void EmitConversion(BoundConversion conversion)
#if DEBUG
#if DEBUG
switch
(
fromPredefTypeKind
)
switch
(
fromPredefTypeKind
)
{
{
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
IntPtr
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
IntPtr
when
!
fromType
.
IsNativeIntegerType
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
when
!
fromType
.
IsNativeIntegerType
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Pointer
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Pointer
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
FunctionPointer
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
FunctionPointer
:
Debug
.
Assert
(
IsNumeric
(
toType
));
Debug
.
Assert
(
IsNumeric
(
toType
));
...
@@ -152,8 +152,7 @@ private void EmitConversion(BoundConversion conversion)
...
@@ -152,8 +152,7 @@ private void EmitConversion(BoundConversion conversion)
default
:
default
:
Debug
.
Assert
(
IsNumeric
(
fromType
));
Debug
.
Assert
(
IsNumeric
(
fromType
));
Debug
.
Assert
(
Debug
.
Assert
(
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
IntPtr
||
(
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
IntPtr
||
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
)
&&
!
toType
.
IsNativeIntegerType
||
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
||
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Pointer
||
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Pointer
||
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
FunctionPointer
);
toPredefTypeKind
==
Microsoft
.
Cci
.
PrimitiveTypeCode
.
FunctionPointer
);
break
;
break
;
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NativeIntegerTests.cs
浏览文件 @
71e6a3be
...
@@ -3,7 +3,6 @@
...
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
// See the LICENSE file in the project root for more information.
using System;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Immutable;
using System.Linq;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols;
...
@@ -6963,16 +6962,8 @@ .maxstack 1
...
@@ -6963,16 +6962,8 @@ .maxstack 1
IL_0006: ret
IL_0006: ret
}");
}");
conversions(sourceType: "string", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "string", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nint", expectedImplicitIL: null,
conversions(sourceType: "void*", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un"));
// https://github.com/dotnet/roslyn/issues/42457: Investigate whether this conversion (and other
conversions(sourceType: "delegate*<void>", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: convNone, expectedCheckedIL: conv("conv.ovf.i.un"));
// 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: "bool", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "bool", destType: "nint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nint", expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u"));
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"));
conversions(sourceType: "sbyte", destType: "nint", expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i"));
...
@@ -7066,12 +7057,35 @@ .maxstack 1
...
@@ -7066,12 +7057,35 @@ .maxstack 1
conversions(sourceType: "string", destType: "nint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "string", destType: "nint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nint?", expectedImplicitIL: null,
conversions(sourceType: "void*", destType: "nint?", expectedImplicitIL: null,
@"{
@"{
// Code size
12 (0xc
)
// Code size
7 (0x7
)
.maxstack 1
.maxstack 1
IL_0000: ldarg.0
IL_0000: ldarg.0
IL_0001: call ""System.IntPtr System.IntPtr.op_Explicit(void*)""
IL_0001: newobj ""nint?..ctor(nint)""
IL_0006: newobj ""nint?..ctor(nint)""
IL_0006: ret
IL_000b: 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: "bool", destType: "nint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nint?", expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint"));
conversions(sourceType: "char", destType: "nint?", expectedImplicitIL: convToNullableT("conv.u", "nint"), expectedExplicitIL: convToNullableT("conv.u", "nint"));
...
@@ -7211,14 +7225,8 @@ .maxstack 1
...
@@ -7211,14 +7225,8 @@ .maxstack 1
IL_0006: ret
IL_0006: ret
}");
}");
conversions(sourceType: "nint", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint", destType: "void*", expectedImplicitIL: null,
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"));
// 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: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
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: "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"));
conversions(sourceType: "nint", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1"));
...
@@ -7315,15 +7323,8 @@ .maxstack 1
...
@@ -7315,15 +7323,8 @@ .maxstack 1
IL_0006: ret
IL_0006: ret
}");
}");
conversions(sourceType: "nint?", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint?", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nint?", destType: "void*", expectedImplicitIL: null,
conversions(sourceType: "nint?", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: null);
@"{
conversions(sourceType: "nint?", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: 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: "bool", 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: "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"));
conversions(sourceType: "nint?", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: convFromNullableT("conv.i1", "nint"), expectedCheckedIL: convFromNullableT("conv.ovf.i1", "nint"));
...
@@ -7421,14 +7422,8 @@ .maxstack 1
...
@@ -7421,14 +7422,8 @@ .maxstack 1
IL_0006: ret
IL_0006: ret
}");
}");
conversions(sourceType: "string", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "string", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nuint", expectedImplicitIL: null,
conversions(sourceType: "void*", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: convNone);
@"{
conversions(sourceType: "delegate*<void>", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: convNone);
// 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: "bool", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "bool", destType: "nuint", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nuint", expectedImplicitIL: conv("conv.u"), expectedExplicitIL: conv("conv.u"));
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"));
conversions(sourceType: "sbyte", destType: "nuint", expectedImplicitIL: conv("conv.i"), expectedExplicitIL: conv("conv.i"), expectedCheckedIL: conv("conv.ovf.u"));
...
@@ -7522,12 +7517,19 @@ .maxstack 1
...
@@ -7522,12 +7517,19 @@ .maxstack 1
conversions(sourceType: "string", destType: "nuint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "string", destType: "nuint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "void*", destType: "nuint?", expectedImplicitIL: null,
conversions(sourceType: "void*", destType: "nuint?", expectedImplicitIL: null,
@"{
@"{
// Code size
12 (0xc
)
// Code size
7 (0x7
)
.maxstack 1
.maxstack 1
IL_0000: ldarg.0
IL_0000: ldarg.0
IL_0001: call ""System.UIntPtr System.UIntPtr.op_Explicit(void*)""
IL_0001: newobj ""nuint?..ctor(nuint)""
IL_0006: newobj ""nuint?..ctor(nuint)""
IL_0006: ret
IL_000b: 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: "bool", destType: "nuint?", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "char", destType: "nuint?", expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint"));
conversions(sourceType: "char", destType: "nuint?", expectedImplicitIL: convToNullableT("conv.u", "nuint"), expectedExplicitIL: convToNullableT("conv.u", "nuint"));
...
@@ -7667,14 +7669,8 @@ .maxstack 1
...
@@ -7667,14 +7669,8 @@ .maxstack 1
IL_0006: ret
IL_0006: ret
}");
}");
conversions(sourceType: "nuint", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint", destType: "void*", expectedImplicitIL: null,
conversions(sourceType: "nuint", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: convNone);
@"{
conversions(sourceType: "nuint", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: convNone);
// 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: "bool", expectedImplicitIL: null, expectedExplicitIL: null);
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: "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"));
conversions(sourceType: "nuint", destType: "sbyte", expectedImplicitIL: null, expectedExplicitIL: conv("conv.i1"), expectedCheckedIL: conv("conv.ovf.i1.un"));
...
@@ -7769,15 +7765,8 @@ .maxstack 1
...
@@ -7769,15 +7765,8 @@ .maxstack 1
IL_0006: ret
IL_0006: ret
}");
}");
conversions(sourceType: "nuint?", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint?", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
conversions(sourceType: "nuint?", destType: "void*", expectedImplicitIL: null,
conversions(sourceType: "nuint?", destType: "void*", expectedImplicitIL: null, expectedExplicitIL: null);
@"{
conversions(sourceType: "nuint?", destType: "delegate*<void>", expectedImplicitIL: null, expectedExplicitIL: 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: "bool", 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: "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"));
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
...
@@ -7883,6 +7872,7 @@ .maxstack 1
}");
}");
conversions(sourceType: "System.IntPtr", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
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: "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: "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: "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"));
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
...
@@ -8020,6 +8010,7 @@ .maxstack 1
}");
}");
conversions(sourceType: "string", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: null);
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: "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: "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: "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)"));
conversions(sourceType: "sbyte", destType: "System.IntPtr", expectedImplicitIL: null, expectedExplicitIL: explicitAndConv("System.IntPtr System.IntPtr.op_Explicit(int)"));
...
@@ -8135,6 +8126,7 @@ .maxstack 1
...
@@ -8135,6 +8126,7 @@ .maxstack 1
}");
}");
conversions(sourceType: "System.UIntPtr", destType: "string", expectedImplicitIL: null, expectedExplicitIL: null);
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: "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: "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: "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"));
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
...
@@ -8330,6 +8322,7 @@ .maxstack 1
}");
}");
conversions(sourceType: "string", destType: "System.UIntPtr", expectedImplicitIL: null, expectedExplicitIL: null);
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: "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: "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: "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"));
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
...
@@ -8481,7 +8474,7 @@ .maxstack 1
verifier.VerifyIL("Program.Convert", expectedIL);
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)
...
@@ -12243,5 +12236,142 @@ static object Execute(Func<object> f)
0
0
{(IntPtr.Size == 4 ? "System.OverflowException" : "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
}");
}
}
}
}
}
src/Compilers/Core/Portable/CodeGen/ILBuilderConversions.cs
浏览文件 @
71e6a3be
...
@@ -7,7 +7,6 @@
...
@@ -7,7 +7,6 @@
using
System
;
using
System
;
using
System.Diagnostics
;
using
System.Diagnostics
;
using
System.Reflection.Metadata
;
using
System.Reflection.Metadata
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Utilities
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CodeGen
namespace
Microsoft.CodeAnalysis.CodeGen
...
@@ -151,6 +150,11 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
...
@@ -151,6 +150,11 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
// Don't want to sign extend if this is a widening conversion.
// Don't want to sign extend if this is a widening conversion.
this
.
EmitOpCode
(
ILOpCode
.
Conv_u
);
// potentially widening, so not NOP
this
.
EmitOpCode
(
ILOpCode
.
Conv_u
);
// potentially widening, so not NOP
break
;
break
;
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Pointer
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
FunctionPointer
:
if
(
@checked
)
goto
default
;
break
;
// NOP
default
:
default
:
if
(
@checked
)
if
(
@checked
)
this
.
EmitOpCode
(
fromUnsigned
?
ILOpCode
.
Conv_ovf_i_un
:
ILOpCode
.
Conv_ovf_i
);
this
.
EmitOpCode
(
fromUnsigned
?
ILOpCode
.
Conv_ovf_i_un
:
ILOpCode
.
Conv_ovf_i
);
...
@@ -164,6 +168,8 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
...
@@ -164,6 +168,8 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
switch
(
fromPredefTypeKind
)
switch
(
fromPredefTypeKind
)
{
{
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Pointer
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
FunctionPointer
:
break
;
// NOP
break
;
// NOP
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UInt8
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UInt8
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UInt16
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UInt16
:
...
@@ -306,6 +312,11 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
...
@@ -306,6 +312,11 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Int64
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
Int64
:
this
.
EmitOpCode
(
ILOpCode
.
Conv_ovf_u
);
this
.
EmitOpCode
(
ILOpCode
.
Conv_ovf_u
);
break
;
break
;
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
IntPtr
:
this
.
EmitOpCode
(
ILOpCode
.
Conv_ovf_u
);
break
;
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
:
break
;
// NOP
default
:
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
fromPredefTypeKind
);
throw
ExceptionUtilities
.
UnexpectedValue
(
fromPredefTypeKind
);
}
}
...
@@ -328,6 +339,9 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
...
@@ -328,6 +339,9 @@ public void EmitNumericConversion(Microsoft.Cci.PrimitiveTypeCode fromPredefType
// rather than conv_u, to sign-extend the value.
// rather than conv_u, to sign-extend the value.
this
.
EmitOpCode
(
ILOpCode
.
Conv_i
);
this
.
EmitOpCode
(
ILOpCode
.
Conv_i
);
break
;
break
;
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
IntPtr
:
case
Microsoft
.
Cci
.
PrimitiveTypeCode
.
UIntPtr
:
break
;
// NOP
default
:
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
fromPredefTypeKind
);
throw
ExceptionUtilities
.
UnexpectedValue
(
fromPredefTypeKind
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录