Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
c99ad715
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,发现更多精彩内容 >>
提交
c99ad715
编写于
1月 09, 2020
作者:
R
Rikki Gibson
提交者:
GitHub
1月 09, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert "Improve the code gen for a conditional access on a readonly unconstrained field (#35979)"
This reverts commit
6b22ff18
.
上级
77728dcc
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
271 addition
and
795 deletion
+271
-795
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
+26
-37
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
...harp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
+0
-282
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
...arp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
+38
-21
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
+142
-88
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
+25
-34
src/Compilers/VisualBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
...alBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
+40
-333
未找到文件。
src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
浏览文件 @
c99ad715
...
...
@@ -405,43 +405,32 @@ private void EmitLoweredConditionalAccessExpression(BoundLoweredConditionalAcces
// if T happens to be a value type, it could be a target of mutating calls.
receiverTemp
=
EmitReceiverRef
(
receiver
,
AddressKind
.
Constrained
);
if
(
receiverTemp
is
null
)
{
// unconstrained case needs to handle case where T is actually a struct.
// such values are never nulls
// we will emit a check for such case, but the check is really a JIT-time
// constant since JIT will know if T is a struct or not.
// if ((object)default(T) != null)
// {
// goto whenNotNull
// }
// else
// {
// temp = receiverRef
// receiverRef = ref temp
// }
EmitDefaultValue
(
receiverType
,
true
,
receiver
.
Syntax
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
cloneTemp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitLocalStore
(
cloneTemp
);
_builder
.
EmitLocalAddress
(
cloneTemp
);
_builder
.
EmitLocalLoad
(
cloneTemp
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
// here we have loaded a ref to a temp and its boxed value { &T, O }
}
else
{
// we are calling the expression on a copy of the target anyway,
// so even if T is a struct, we don't need to make sure we call the expression on the original target.
_builder
.
EmitLocalLoad
(
receiverTemp
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
}
// unconstrained case needs to handle case where T is actually a struct.
// such values are never nulls
// we will emit a check for such case, but the check is really a JIT-time
// constant since JIT will know if T is a struct or not.
// if ((object)default(T) != null)
// {
// goto whenNotNull
// }
// else
// {
// temp = receiverRef
// receiverRef = ref temp
// }
EmitDefaultValue
(
receiverType
,
true
,
receiver
.
Syntax
);
EmitBox
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
);
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
);
cloneTemp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
);
_builder
.
EmitLocalStore
(
cloneTemp
);
_builder
.
EmitLocalAddress
(
cloneTemp
);
_builder
.
EmitLocalLoad
(
cloneTemp
);
EmitBox
(
receiver
.
Type
,
receiver
.
Syntax
);
// here we have loaded a ref to a temp and its boxed value { &T, O }
}
else
{
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenConditionalOperatorTests.cs
浏览文件 @
c99ad715
...
...
@@ -2763,287 +2763,5 @@ .maxstack 1
IL_0064: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessUnconstrainedTField
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
private T t;
public void Print()
{
Console.WriteLine(t?.ToString());
Console.WriteLine(t);
}
}
public struct S
{
int a;
public override string ToString() => a++.ToString();
}
public static class Program
{
public static void Main()
{
new C<S>().Print();
new C<S?>().Print();
new C<S?>(new S()).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
1
0
0
hello
hello"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 75 (0x4b)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldflda ""T C<T>.t""
IL_0006: ldloca.s V_0
IL_0008: initobj ""T""
IL_000e: ldloc.0
IL_000f: box ""T""
IL_0014: brtrue.s IL_002a
IL_0016: ldobj ""T""
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldloc.0
IL_001f: box ""T""
IL_0024: brtrue.s IL_002a
IL_0026: pop
IL_0027: ldnull
IL_0028: br.s IL_0035
IL_002a: constrained. ""T""
IL_0030: callvirt ""string object.ToString()""
IL_0035: call ""void System.Console.WriteLine(string)""
IL_003a: ldarg.0
IL_003b: ldfld ""T C<T>.t""
IL_0040: box ""T""
IL_0045: call ""void System.Console.WriteLine(object)""
IL_004a: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessReadonlyUnconstrainedTField
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
readonly T t;
public void Print()
{
Console.WriteLine(t?.ToString());
Console.WriteLine(t);
}
}
public struct S
{
int a;
public override string ToString() => a++.ToString();
}
public static class Program
{
public static void Main()
{
new C<S>().Print();
new C<S?>().Print();
new C<S?>(new S()).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}
"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
0
0
0
hello
hello"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 54 (0x36)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldfld ""T C<T>.t""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box ""T""
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. ""T""
IL_001b: callvirt ""string object.ToString()""
IL_0020: call ""void System.Console.WriteLine(string)""
IL_0025: ldarg.0
IL_0026: ldfld ""T C<T>.t""
IL_002b: box ""T""
IL_0030: call ""void System.Console.WriteLine(object)""
IL_0035: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessUnconstrainedTLocal
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
private T t;
public void Print()
{
var temp = t;
Console.WriteLine(temp?.ToString());
Console.WriteLine(temp);
}
}
public struct S
{
int a;
public override string ToString() => a++.ToString();
}
public static class Program
{
public static void Main()
{
new C<S>().Print();
new C<S?>().Print();
new C<S?>(new S()).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
1
0
1
hello
hello"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 48 (0x30)
.maxstack 1
.locals init (T V_0) //temp
IL_0000: ldarg.0
IL_0001: ldfld ""T C<T>.t""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: box ""T""
IL_000d: brtrue.s IL_0012
IL_000f: ldnull
IL_0010: br.s IL_001f
IL_0012: ldloca.s V_0
IL_0014: constrained. ""T""
IL_001a: callvirt ""string object.ToString()""
IL_001f: call ""void System.Console.WriteLine(string)""
IL_0024: ldloc.0
IL_0025: box ""T""
IL_002a: call ""void System.Console.WriteLine(object)""
IL_002f: ret
}"
);
}
[
Fact
]
[
WorkItem
(
3519
,
"https://github.com/dotnet/roslyn/issues/35319"
)]
public
void
ConditionalAccessUnconstrainedTTemp
()
{
var
source
=
@"using System;
public class C<T>
{
public C(T t) => this.t = t;
public C(){}
T t;
T M() => t;
public void Print() => Console.WriteLine(M()?.ToString());
}
public static class Program
{
public static void Main()
{
new C<int>().Print();
new C<int?>().Print();
new C<int?>(0).Print();
new C<string>(""hello"").Print();
new C<string>().Print();
}
}
"
;
var
verify
=
CompileAndVerify
(
source
,
expectedOutput
:
@"0
0
hello
"
);
verify
.
VerifyIL
(
"C<T>.Print()"
,
@"
{
// Code size 38 (0x26)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: call ""T C<T>.M()""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box ""T""
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. ""T""
IL_001b: callvirt ""string object.ToString()""
IL_0020: call ""void System.Console.WriteLine(string)""
IL_0025: ret
}"
);
}
}
}
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenShortCircuitOperatorTests.cs
浏览文件 @
c99ad715
...
...
@@ -2461,32 +2461,49 @@ static void Main(string[] args)
False"
);
comp
.
VerifyIL
(
"Program.Test<T>(System.Func<T>)"
,
@"
{
// Code size
62 (0x3
e)
// Code size
110 (0x6
e)
.maxstack 2
.locals init (T V_0)
.locals init (T V_0,
T V_1)
IL_0000: ldarg.0
IL_0001: callvirt ""T System.Func<T>.Invoke()""
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box ""T""
IL_000f: brtrue.s IL_0014
IL_0011: pop
IL_0012: br.s IL_001f
IL_0014: constrained. ""T""
IL_001a: callvirt ""void System.IDisposable.Dispose()""
IL_001f: ldarg.0
IL_0020: callvirt ""T System.Func<T>.Invoke()""
IL_0025: stloc.0
IL_0026: ldloca.s V_0
IL_0028: ldloc.0
IL_0029: box ""T""
IL_002e: brtrue.s IL_0032
IL_0030: pop
IL_0031: ret
IL_0032: constrained. ""T""
IL_0038: callvirt ""void System.IDisposable.Dispose()""
IL_003d: ret
IL_0009: ldloca.s V_1
IL_000b: initobj ""T""
IL_0011: ldloc.1
IL_0012: box ""T""
IL_0017: brtrue.s IL_002c
IL_0019: ldobj ""T""
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
IL_0022: box ""T""
IL_0027: brtrue.s IL_002c
IL_0029: pop
IL_002a: br.s IL_0037
IL_002c: constrained. ""T""
IL_0032: callvirt ""void System.IDisposable.Dispose()""
IL_0037: ldarg.0
IL_0038: callvirt ""T System.Func<T>.Invoke()""
IL_003d: stloc.0
IL_003e: ldloca.s V_0
IL_0040: ldloca.s V_1
IL_0042: initobj ""T""
IL_0048: ldloc.1
IL_0049: box ""T""
IL_004e: brtrue.s IL_0062
IL_0050: ldobj ""T""
IL_0055: stloc.1
IL_0056: ldloca.s V_1
IL_0058: ldloc.1
IL_0059: box ""T""
IL_005e: brtrue.s IL_0062
IL_0060: pop
IL_0061: ret
IL_0062: constrained. ""T""
IL_0068: callvirt ""void System.IDisposable.Dispose()""
IL_006d: ret
}
"
);
}
...
...
src/Compilers/CSharp/Test/WinRT/AnonymousTypesSymbolTests.cs
浏览文件 @
c99ad715
...
...
@@ -424,11 +424,14 @@ .maxstack 3
).
VerifyIL
(
"<>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.ToString"
,
@"{
// Code size 1
23 (0x7b
)
// Code size 1
99 (0xc7
)
.maxstack 7
.locals init (<Length>j__TPar V_0,
<at1>j__TPar V_1,
<C>j__TPar V_2)
<Length>j__TPar V_1,
<at1>j__TPar V_2,
<at1>j__TPar V_3,
<C>j__TPar V_4,
<C>j__TPar V_5)
IL_0000: ldnull
IL_0001: ldstr ""{{ Length = {0}, at1 = {1}, C = {2} }}""
IL_0006: ldc.i4.3
...
...
@@ -439,47 +442,71 @@ .maxstack 7
IL_000f: ldfld ""<Length>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<Length>i__Field""
IL_0014: stloc.0
IL_0015: ldloca.s V_0
IL_0017: ldloc.0
IL_0018: box ""<Length>j__TPar""
IL_001d: brtrue.s IL_0023
IL_001f: pop
IL_0020: ldnull
IL_0021: br.s IL_002e
IL_0023: constrained. ""<Length>j__TPar""
IL_0029: callvirt ""string object.ToString()""
IL_002e: stelem.ref
IL_002f: dup
IL_0030: ldc.i4.1
IL_0031: ldarg.0
IL_0032: ldfld ""<at1>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<at1>i__Field""
IL_0037: stloc.1
IL_0038: ldloca.s V_1
IL_003a: ldloc.1
IL_003b: box ""<at1>j__TPar""
IL_0040: brtrue.s IL_0046
IL_0042: pop
IL_0043: ldnull
IL_0044: br.s IL_0051
IL_0046: constrained. ""<at1>j__TPar""
IL_004c: callvirt ""string object.ToString()""
IL_0051: stelem.ref
IL_0052: dup
IL_0053: ldc.i4.2
IL_0054: ldarg.0
IL_0055: ldfld ""<C>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<C>i__Field""
IL_005a: stloc.2
IL_005b: ldloca.s V_2
IL_005d: ldloc.2
IL_005e: box ""<C>j__TPar""
IL_0063: brtrue.s IL_0069
IL_0065: pop
IL_0066: ldnull
IL_0067: br.s IL_0074
IL_0069: constrained. ""<C>j__TPar""
IL_006f: callvirt ""string object.ToString()""
IL_0074: stelem.ref
IL_0075: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_007a: ret
IL_0017: ldloca.s V_1
IL_0019: initobj ""<Length>j__TPar""
IL_001f: ldloc.1
IL_0020: box ""<Length>j__TPar""
IL_0025: brtrue.s IL_003b
IL_0027: ldobj ""<Length>j__TPar""
IL_002c: stloc.1
IL_002d: ldloca.s V_1
IL_002f: ldloc.1
IL_0030: box ""<Length>j__TPar""
IL_0035: brtrue.s IL_003b
IL_0037: pop
IL_0038: ldnull
IL_0039: br.s IL_0046
IL_003b: constrained. ""<Length>j__TPar""
IL_0041: callvirt ""string object.ToString()""
IL_0046: stelem.ref
IL_0047: dup
IL_0048: ldc.i4.1
IL_0049: ldarg.0
IL_004a: ldfld ""<at1>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<at1>i__Field""
IL_004f: stloc.2
IL_0050: ldloca.s V_2
IL_0052: ldloca.s V_3
IL_0054: initobj ""<at1>j__TPar""
IL_005a: ldloc.3
IL_005b: box ""<at1>j__TPar""
IL_0060: brtrue.s IL_0076
IL_0062: ldobj ""<at1>j__TPar""
IL_0067: stloc.3
IL_0068: ldloca.s V_3
IL_006a: ldloc.3
IL_006b: box ""<at1>j__TPar""
IL_0070: brtrue.s IL_0076
IL_0072: pop
IL_0073: ldnull
IL_0074: br.s IL_0081
IL_0076: constrained. ""<at1>j__TPar""
IL_007c: callvirt ""string object.ToString()""
IL_0081: stelem.ref
IL_0082: dup
IL_0083: ldc.i4.2
IL_0084: ldarg.0
IL_0085: ldfld ""<C>j__TPar <>f__AnonymousType1<<Length>j__TPar, <at1>j__TPar, <C>j__TPar>.<C>i__Field""
IL_008a: stloc.s V_4
IL_008c: ldloca.s V_4
IL_008e: ldloca.s V_5
IL_0090: initobj ""<C>j__TPar""
IL_0096: ldloc.s V_5
IL_0098: box ""<C>j__TPar""
IL_009d: brtrue.s IL_00b5
IL_009f: ldobj ""<C>j__TPar""
IL_00a4: stloc.s V_5
IL_00a6: ldloca.s V_5
IL_00a8: ldloc.s V_5
IL_00aa: box ""<C>j__TPar""
IL_00af: brtrue.s IL_00b5
IL_00b1: pop
IL_00b2: ldnull
IL_00b3: br.s IL_00c0
IL_00b5: constrained. ""<C>j__TPar""
IL_00bb: callvirt ""string object.ToString()""
IL_00c0: stelem.ref
IL_00c1: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_00c6: ret
}"
);
}
...
...
@@ -846,11 +873,14 @@ .maxstack 3
).
VerifyIL
(
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString"
,
@"{
// Code size 1
23 (0x7b
)
// Code size 1
99 (0xc7
)
.maxstack 7
.locals init (<ToString>j__TPar V_0,
<Equals>j__TPar V_1,
<GetHashCode>j__TPar V_2)
<ToString>j__TPar V_1,
<Equals>j__TPar V_2,
<Equals>j__TPar V_3,
<GetHashCode>j__TPar V_4,
<GetHashCode>j__TPar V_5)
IL_0000: ldnull
IL_0001: ldstr ""{{ ToString = {0}, Equals = {1}, GetHashCode = {2} }}""
IL_0006: ldc.i4.3
...
...
@@ -861,47 +891,71 @@ .maxstack 7
IL_000f: ldfld ""<ToString>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<ToString>i__Field""
IL_0014: stloc.0
IL_0015: ldloca.s V_0
IL_0017: ldloc.0
IL_0018: box ""<ToString>j__TPar""
IL_001d: brtrue.s IL_0023
IL_001f: pop
IL_0020: ldnull
IL_0021: br.s IL_002e
IL_0023: constrained. ""<ToString>j__TPar""
IL_0029: callvirt ""string object.ToString()""
IL_002e: stelem.ref
IL_002f: dup
IL_0030: ldc.i4.1
IL_0031: ldarg.0
IL_0032: ldfld ""<Equals>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<Equals>i__Field""
IL_0037: stloc.1
IL_0038: ldloca.s V_1
IL_003a: ldloc.1
IL_003b: box ""<Equals>j__TPar""
IL_0040: brtrue.s IL_0046
IL_0042: pop
IL_0043: ldnull
IL_0044: br.s IL_0051
IL_0046: constrained. ""<Equals>j__TPar""
IL_004c: callvirt ""string object.ToString()""
IL_0051: stelem.ref
IL_0052: dup
IL_0053: ldc.i4.2
IL_0054: ldarg.0
IL_0055: ldfld ""<GetHashCode>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<GetHashCode>i__Field""
IL_005a: stloc.2
IL_005b: ldloca.s V_2
IL_005d: ldloc.2
IL_005e: box ""<GetHashCode>j__TPar""
IL_0063: brtrue.s IL_0069
IL_0065: pop
IL_0066: ldnull
IL_0067: br.s IL_0074
IL_0069: constrained. ""<GetHashCode>j__TPar""
IL_006f: callvirt ""string object.ToString()""
IL_0074: stelem.ref
IL_0075: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_007a: ret
IL_0017: ldloca.s V_1
IL_0019: initobj ""<ToString>j__TPar""
IL_001f: ldloc.1
IL_0020: box ""<ToString>j__TPar""
IL_0025: brtrue.s IL_003b
IL_0027: ldobj ""<ToString>j__TPar""
IL_002c: stloc.1
IL_002d: ldloca.s V_1
IL_002f: ldloc.1
IL_0030: box ""<ToString>j__TPar""
IL_0035: brtrue.s IL_003b
IL_0037: pop
IL_0038: ldnull
IL_0039: br.s IL_0046
IL_003b: constrained. ""<ToString>j__TPar""
IL_0041: callvirt ""string object.ToString()""
IL_0046: stelem.ref
IL_0047: dup
IL_0048: ldc.i4.1
IL_0049: ldarg.0
IL_004a: ldfld ""<Equals>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<Equals>i__Field""
IL_004f: stloc.2
IL_0050: ldloca.s V_2
IL_0052: ldloca.s V_3
IL_0054: initobj ""<Equals>j__TPar""
IL_005a: ldloc.3
IL_005b: box ""<Equals>j__TPar""
IL_0060: brtrue.s IL_0076
IL_0062: ldobj ""<Equals>j__TPar""
IL_0067: stloc.3
IL_0068: ldloca.s V_3
IL_006a: ldloc.3
IL_006b: box ""<Equals>j__TPar""
IL_0070: brtrue.s IL_0076
IL_0072: pop
IL_0073: ldnull
IL_0074: br.s IL_0081
IL_0076: constrained. ""<Equals>j__TPar""
IL_007c: callvirt ""string object.ToString()""
IL_0081: stelem.ref
IL_0082: dup
IL_0083: ldc.i4.2
IL_0084: ldarg.0
IL_0085: ldfld ""<GetHashCode>j__TPar <>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.<GetHashCode>i__Field""
IL_008a: stloc.s V_4
IL_008c: ldloca.s V_4
IL_008e: ldloca.s V_5
IL_0090: initobj ""<GetHashCode>j__TPar""
IL_0096: ldloc.s V_5
IL_0098: box ""<GetHashCode>j__TPar""
IL_009d: brtrue.s IL_00b5
IL_009f: ldobj ""<GetHashCode>j__TPar""
IL_00a4: stloc.s V_5
IL_00a6: ldloca.s V_5
IL_00a8: ldloc.s V_5
IL_00aa: box ""<GetHashCode>j__TPar""
IL_00af: brtrue.s IL_00b5
IL_00b1: pop
IL_00b2: ldnull
IL_00b3: br.s IL_00c0
IL_00b5: constrained. ""<GetHashCode>j__TPar""
IL_00bb: callvirt ""string object.ToString()""
IL_00c0: stelem.ref
IL_00c1: call ""string string.Format(System.IFormatProvider, string, params object[])""
IL_00c6: ret
}"
).
VerifyIL
(
"<>f__AnonymousType0<<ToString>j__TPar, <Equals>j__TPar, <GetHashCode>j__TPar>.ToString.get"
,
...
...
src/Compilers/VisualBasic/Portable/CodeGen/EmitExpression.vb
浏览文件 @
c99ad715
...
...
@@ -288,43 +288,35 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
Dim
nullCheckOnCopy
=
conditional
.
CaptureReceiver
OrElse
(
receiverType
.
IsReferenceType
AndAlso
receiverType
.
TypeKind
=
TypeKind
.
TypeParameter
)
If
nullCheckOnCopy
Then
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
If
Not
receiverType
.
IsReferenceType
Then
If
receiverTemp
Is
Nothing
Then
' unconstrained case needs to handle case where T Is actually a struct.
' such values are never nulls
' we will emit a check for such case, but the check Is really a JIT-time
' constant since JIT will know if T Is a struct Or Not.
'
' if ((object)default(T) != null)
' {
' goto whenNotNull
' }
' else
' {
' temp = receiverRef
' receiverRef = ref temp
' }
EmitInitObj
(
receiverType
,
True
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
temp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitLocalStore
(
temp
)
_builder
.
EmitLocalAddress
(
temp
)
_builder
.
EmitLocalLoad
(
temp
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
' unconstrained case needs to handle case where T Is actually a struct.
' such values are never nulls
' we will emit a check for such case, but the check Is really a JIT-time
' constant since JIT will know if T Is a struct Or Not.
'
' if ((object)default(T) != null)
' {
' goto whenNotNull
' }
' else
' {
' temp = receiverRef
' receiverRef = ref temp
' }
EmitInitObj
(
receiverType
,
True
,
receiver
.
Syntax
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitBranch
(
ILOpCode
.
Brtrue
,
whenNotNullLabel
)
EmitLoadIndirect
(
receiverType
,
receiver
.
Syntax
)
' here we have loaded a ref to a temp And its boxed value { &T, O }
Else
' we are calling the expression on a copy of the target anyway,
' so even if T is a struct, we don't need to make sure we call the expression on the original target.
temp
=
AllocateTemp
(
receiverType
,
receiver
.
Syntax
)
_builder
.
EmitLocalStore
(
temp
)
_builder
.
EmitLocalAddress
(
temp
)
_builder
.
EmitLocalLoad
(
temp
)
EmitBox
(
receiver
.
Type
,
receiver
.
Syntax
)
_builder
.
EmitLocalLoad
(
receiverTemp
)
EmitBox
(
receiverType
,
receiver
.
Syntax
)
End
If
' here we have loaded a ref to a temp And its boxed value { &T, O }
Else
_builder
.
EmitOpCode
(
ILOpCode
.
Dup
)
' here we have loaded two copies of a reference { O, O }
...
...
@@ -368,7 +360,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
_builder
.
MarkLabel
(
whenNotNullLabel
)
If
Not
nullCheckOnCopy
Then
Debug
.
Assert
(
receiverTemp
Is
Nothing
)
receiverTemp
=
EmitReceiverRef
(
receiver
,
isAccessConstrained
:
=
Not
receiverType
.
IsReferenceType
,
addressKind
:
=
AddressKind
.
ReadOnly
)
Debug
.
Assert
(
receiverTemp
Is
Nothing
OrElse
receiver
.
IsDefaultValue
())
End
If
...
...
src/Compilers/VisualBasic/Test/Semantic/Semantics/ConditionalAccessTests.vb
浏览文件 @
c99ad715
...
...
@@ -613,23 +613,32 @@ Null
verifier.VerifyIL("
Module1
.
Test8
",
<![CDATA[
{
// Code size
38 (0x26
)
// Code size
62 (0x3e
)
.maxstack 2
.locals init (T V_0)
.locals init (T V_0,
T V_1)
IL_0000: ldarg.0
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box "
T
"
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
I1
.
get_P2
()
As
String
"
IL_0020: call "
Sub
Module1
.
Do
(
Of
String
)(
String
)
"
IL_0025: ret
IL_0009: ldloca.s V_1
IL_000b: initobj "
T
"
IL_0011: ldloc.1
IL_0012: box "
T
"
IL_0017: brtrue.s IL_002d
IL_0019: ldobj "
T
"
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
IL_0022: box "
T
"
IL_0027: brtrue.s IL_002d
IL_0029: pop
IL_002a: ldnull
IL_002b: br.s IL_0038
IL_002d: constrained. "
T
"
IL_0033: callvirt "
Function
I1
.
get_P2
()
As
String
"
IL_0038: call "
Sub
Module1
.
Do
(
Of
String
)(
String
)
"
IL_003d: ret
}
]]>)
...
...
@@ -3543,21 +3552,30 @@ Ext4 C1
verifier.VerifyIL("
Module1
.
Test1_6
",
<![CDATA[
{
// Code size
30 (0x1e
)
// Code size
54 (0x36
)
.maxstack 2
.locals init (T V_0)
.locals init (T V_0,
T V_1)
IL_0000: ldarg.0
IL_0001: call "
Function
Module1
.
GetT
(
Of
T
)(
T
)
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box "
T
"
IL_000f: brtrue.s IL_0013
IL_0011: pop
IL_0012: ret
IL_0013: ldobj "
T
"
IL_0018: call "
Sub
Module1
.
Ext1
(
Of
T
)(
T
)
"
IL_001d: ret
IL_0009: ldloca.s V_1
IL_000b: initobj "
T
"
IL_0011: ldloc.1
IL_0012: box "
T
"
IL_0017: brtrue.s IL_002b
IL_0019: ldobj "
T
"
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloc.1
IL_0022: box "
T
"
IL_0027: brtrue.s IL_002b
IL_0029: pop
IL_002a: ret
IL_002b: ldobj "
T
"
IL_0030: call "
Sub
Module1
.
Ext1
(
Of
T
)(
T
)
"
IL_0035: ret
}
]]>)
...
...
@@ -5288,317 +5306,6 @@ C1
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessUnconstrainedTField()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(t As T)
field = t
End Sub
Public Sub New()
End Sub
Private field As T
Public Sub Print()
Console.WriteLine(field?.ToString())
Console.WriteLine(field)
End Sub
End Class
Public Structure S
Private a As Integer
Public Overrides Function ToString() As String
Dim result = a.ToString()
a = a + 1
Return result
End Function
End Structure
Module Program
Sub Main()
Call New C(Of S)().Print()
Call New C(Of S?)().Print()
Call New C(Of S?)(New S()).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
1
0
0
hello
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 75 (0x4b)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldflda "C
(
Of
T
).
field
As
T
"
IL_0006: ldloca.s V_0
IL_0008: initobj "
T
"
IL_000e: ldloc.0
IL_000f: box "
T
"
IL_0014: brtrue.s IL_002a
IL_0016: ldobj "
T
"
IL_001b: stloc.0
IL_001c: ldloca.s V_0
IL_001e: ldloc.0
IL_001f: box "
T
"
IL_0024: brtrue.s IL_002a
IL_0026: pop
IL_0027: ldnull
IL_0028: br.s IL_0035
IL_002a: constrained. "
T
"
IL_0030: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0035: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_003a: ldarg.0
IL_003b: ldfld "C
(
Of
T
).
field
As
T
"
IL_0040: box "
T
"
IL_0045: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_004a: ret
}
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessReadonlyUnconstrainedTField()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(ByVal t As T)
field = t
End Sub
Public Sub New()
End Sub
ReadOnly field As T
Public Sub Print()
Console.WriteLine(field?.ToString())
Console.WriteLine(field)
End Sub
End Class
Public Structure S
Private a As Integer
Public Overrides Function ToString() As String
Return Math.Min(System.Threading.Interlocked.Increment(a), a - 1).ToString()
End Function
End Structure
Module Program
Sub Main()
Call New C(Of S)().Print()
Call New C(Of S?)().Print()
Call New C(Of S?)(New S()).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
0
0
0
hello
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 54 (0x36)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: ldfld "C
(
Of
T
).
field
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box "
T
"
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0020: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_0025: ldarg.0
IL_0026: ldfld "C
(
Of
T
).
field
As
T
"
IL_002b: box "
T
"
IL_0030: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_0035: ret
}
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessUnconstrainedTLocal()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(ByVal t As T)
field = t
End Sub
Public Sub New()
End Sub
Private field As T
Public Sub Print()
Dim temp = field
Console.WriteLine(temp?.ToString())
Console.WriteLine(temp)
End Sub
End Class
Public Structure S
Private a As Integer
Public Overrides Function ToString() As String
Return Math.Min(System.Threading.Interlocked.Increment(a), a - 1).ToString()
End Function
End Structure
Module Program
Sub Main()
Call New C(Of S)().Print()
Call New C(Of S?)().Print()
Call New C(Of S?)(New S()).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
1
0
1
hello
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 48 (0x30)
.maxstack 1
.locals init (T V_0) //temp
IL_0000: ldarg.0
IL_0001: ldfld "C
(
Of
T
).
field
As
T
"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: box "
T
"
IL_000d: brtrue.s IL_0012
IL_000f: ldnull
IL_0010: br.s IL_001f
IL_0012: ldloca.s V_0
IL_0014: constrained. "
T
"
IL_001a: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_001f: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_0024: ldloc.0
IL_0025: box "
T
"
IL_002a: call "
Sub
System
.
Console
.
WriteLine
(
Object
)
"
IL_002f: ret
}
]]>)
End Sub
<Fact>
<WorkItem(3519, "
https
:
//
github
.
com
/
dotnet
/
roslyn
/
issues
/
35319
")>
Public Sub CodeGen_ConditionalAccessUnconstrainedTTemp()
Dim c = CompileAndVerify(
<compilation>
<file name="
a
.
vb
">
Imports System
Public Class C(Of T)
Public Sub New(ByVal t As T)
field = t
End Sub
Public Sub New()
End Sub
Private field As T
Private Function M() As T
Return field
End Function
Public Sub Print()
Console.WriteLine(M()?.ToString())
End Sub
End Class
Module Program
Sub Main()
Call New C(Of Integer)().Print()
Call New C(Of Integer?)().Print()
Call New C(Of Integer?)(0).Print()
Call New C(Of String)("
hello
").Print()
Call New C(Of String)().Print()
End Sub
End Module
</file>
</compilation>, expectedOutput:="
0
0
hello
")
c.VerifyIL("C
(
Of
T
).
Print
()
",
<![CDATA[
{
// Code size 38 (0x26)
.maxstack 2
.locals init (T V_0)
IL_0000: ldarg.0
IL_0001: call "
Function
C
(
Of
T
).
M
()
As
T
"
IL_0006: stloc.0
IL_0007: ldloca.s V_0
IL_0009: ldloc.0
IL_000a: box "
T
"
IL_000f: brtrue.s IL_0015
IL_0011: pop
IL_0012: ldnull
IL_0013: br.s IL_0020
IL_0015: constrained. "
T
"
IL_001b: callvirt "
Function
Object
.
ToString
()
As
String
"
IL_0020: call "
Sub
System
.
Console
.
WriteLine
(
String
)
"
IL_0025: ret
}
]]>)
End Sub
<Fact()>
Public Sub InlineNullableIsTrue_01()
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录