未验证 提交 2f6c1c58 编写于 作者: C Charles Stoner 提交者: GitHub

Avoid using a ref local for array element l-value (#24070)

上级 bb5d3736
......@@ -507,29 +507,30 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
break;
case BoundKind.ArrayAccess:
if (isDynamicAssignment)
{
// In non-dynamic array[index] op= R we emit:
// T& tmp = &array[index];
// *tmp = *L op R;
// where T is the type of L.
//
// If L is an array access, the assignment is dynamic, the compile-time of the array is dynamic[]
// and the runtime type of the array is not object[] (but e.g. string[]) the pointer approach is broken.
// T is Object in such case and we can't take a read-write pointer of type Object& to an array element of non-object type.
//
// In this case we rewrite the assignment as follows:
//
// E t_array = array;
// I t_index = index; (possibly more indices)
// T value = t_array[t_index];
// t_array[t_index] = value op R;
var arrayAccess = (BoundArrayAccess)originalLHS;
var loweredArray = VisitExpression(arrayAccess.Expression);
var loweredIndices = VisitList(arrayAccess.Indices);
return SpillArrayElementAccess(loweredArray, loweredIndices, stores, temps);
if (isDynamicAssignment || !IsInvariantArray(arrayAccess.Expression.Type))
{
// In non-dynamic, invariant array[index] op= R we emit:
// T& tmp = &array[index];
// *tmp = *L op R;
// where T is the type of L.
//
// If L is an array access, the assignment is dynamic, the compile-time of the array is dynamic[]
// and the runtime type of the array is not object[] (but e.g. string[]) the pointer approach is broken.
// T is Object in such case and we can't take a read-write pointer of type Object& to an array element of non-object type.
//
// In the dynamic case, or when the array may be co-variant, we rewrite the assignment as follows:
//
// E t_array = array;
// I t_index = index; (possibly more indices)
// T value = t_array[t_index];
// t_array[t_index] = value op R;
var loweredArray = VisitExpression(arrayAccess.Expression);
var loweredIndices = VisitList(arrayAccess.Indices);
return SpillArrayElementAccess(loweredArray, loweredIndices, stores, temps);
}
}
break;
......@@ -603,6 +604,11 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL
return variableTemp;
}
private static bool IsInvariantArray(TypeSymbol type)
{
return (type as ArrayTypeSymbol)?.ElementType.IsSealed == true;
}
private BoundExpression BoxReceiver(BoundExpression rewrittenReceiver, NamedTypeSymbol memberContainingType)
{
return MakeConversionNode(
......
......@@ -4860,7 +4860,7 @@ .locals init (int? V_0)
}
[Fact]
public void TestCompoundOnAfieldOfGeneric()
public void TestCompoundOnAFieldOfGeneric()
{
var source = @"
class Program
......
......@@ -16073,5 +16073,209 @@ public static void Main()
CompileAndVerify(comp, expectedOutput: "SpanOpCalled", verify: Verification.Fails);
}
[Fact]
public void ArrayElementCompoundAssignment_Invariant()
{
string source =
@"class C
{
static void Main()
{
F(new string[] { """" }, ""B"");
}
static void F(string[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(string[] a, string s)
{
a[0] += s;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "B");
verifier.VerifyIL("C.G",
@"{
// Code size 17 (0x11)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""string""
IL_0007: dup
IL_0008: ldind.ref
IL_0009: ldarg.1
IL_000a: call ""string string.Concat(string, string)""
IL_000f: stind.ref
IL_0010: ret
}");
}
[WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")]
[Fact]
public void ArrayElementCompoundAssignment_Covariant()
{
string source =
@"class C
{
static void Main()
{
F(new object[] { """" }, ""A"");
F(new string[] { """" }, ""B"");
}
static void F(object[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(object[] a, string s)
{
a[0] += s;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "AB");
verifier.VerifyIL("C.G",
@"{
// Code size 15 (0xf)
.maxstack 4
.locals init (object[] V_0)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: ldc.i4.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: ldelem.ref
IL_0007: ldarg.1
IL_0008: call ""string string.Concat(object, object)""
IL_000d: stelem.ref
IL_000e: ret
}");
}
[Fact]
public void ArrayElementCompoundAssignment_ValueType()
{
string source =
@"class C
{
static void Main()
{
F(new int[] { 1 }, 2);
}
static void F(int[] a, int i)
{
G(a, i);
System.Console.Write(a[0]);
}
static void G(int[] a, int i)
{
a[0] += i;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "3");
verifier.VerifyIL("C.G",
@"{
// Code size 13 (0xd)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""int""
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldarg.1
IL_000a: add
IL_000b: stind.i4
IL_000c: ret
}");
}
[WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")]
[Fact]
public void ArrayElementCompoundAssignment_Covariant_NonConstantIndex()
{
string source =
@"class C
{
static void Main()
{
F(new object[] { """" }, ""A"");
F(new string[] { """" }, ""B"");
}
static void F(object[] a, string s)
{
G(a, s);
System.Console.Write(a[0]);
}
static void G(object[] a, string s)
{
a[Index(a)] += s;
}
static int Index(object arg)
{
System.Console.Write(arg.GetType().Name);
return 0;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "Object[]AString[]B");
verifier.VerifyIL("C.G",
@"{
// Code size 22 (0x16)
.maxstack 4
.locals init (object[] V_0,
int V_1)
IL_0000: ldarg.0
IL_0001: stloc.0
IL_0002: ldarg.0
IL_0003: call ""int C.Index(object)""
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: ldloc.1
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: ldelem.ref
IL_000e: ldarg.1
IL_000f: call ""string string.Concat(object, object)""
IL_0014: stelem.ref
IL_0015: ret
}");
}
[Fact]
public void ArrayElementIncrement_ValueType()
{
string source =
@"class C
{
static void Main()
{
F(new int[] { 1 });
}
static void F(int[] a)
{
G(a);
System.Console.Write(a[0]);
}
static void G(int[] a)
{
a[0]++;
}
}";
var verifier = CompileAndVerify(source, expectedOutput: "2");
verifier.VerifyIL("C.G",
@"{
// Code size 13 (0xd)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema ""int""
IL_0007: dup
IL_0008: ldind.i4
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stind.i4
IL_000c: ret
}");
}
}
}
......@@ -209,6 +209,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(node.IsLValue)
#If DONT_USE_BYREF_LOCALS_FOR_USE_TWICE Then
#Else
If IsInvariantArray(node.Expression.Type) Then
Return UseTwiceLValue(containingMember, node, arg)
End If
#End If
' Note, as an alternative we could capture reference to the array element in a ByRef temp.
' However, without an introduction of an indirect assignment node, IL-gen is unable to distinguish
' when it should assign indirect or should assign a reference. For now, decided to not introduce
......@@ -232,9 +238,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(first.IsLValue AndAlso second.IsLValue)
Return New Result(first, second)
#Else
Return UseTwiceLValue(containingMember, node, arg)
#End If
End Function
Private Shared Function IsInvariantArray(type As TypeSymbol) As Boolean
Dim value = TryCast(type, ArrayTypeSymbol)?.ElementType.IsNotInheritable
Return value.GetValueOrDefault()
End Function
Private Shared Function UseTwiceLValue(containingMember As Symbol, lvalue As BoundExpression, temporaries As ArrayBuilder(Of SynthesizedLocal)) As Result
......@@ -274,8 +283,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' easier to implement.
Dim receiver As Result = UseTwiceReceiver(containingMember, node.ReceiverOpt, arg)
Dim first = node.Update(receiver.First, fieldSymbol, node.IsLValue, node.ConstantsInProgressOpt, node.Type)
Dim second = node.Update(receiver.Second, fieldSymbol, node.IsLValue, node.ConstantsInProgressOpt, node.Type)
Dim first = node.Update(receiver.First, fieldSymbol, node.IsLValue, suppressVirtualCalls:=False, node.ConstantsInProgressOpt, node.Type)
Dim second = node.Update(receiver.Second, fieldSymbol, node.IsLValue, suppressVirtualCalls:=False, node.ConstantsInProgressOpt, node.Type)
Debug.Assert(first.IsLValue AndAlso second.IsLValue)
Return New Result(first, second)
......@@ -496,7 +505,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Sub
#If DONT_USE_BYREF_LOCALS_FOR_USE_TWICE Then
Private Shared Function UseTwiceReceiver(containingMember As Symbol, receiverOpt As BoundExpression, arg As ArrayBuilder(Of TempLocalSymbol)) As Result
Private Shared Function UseTwiceReceiver(containingMember As Symbol, receiverOpt As BoundExpression, arg As ArrayBuilder(Of SynthesizedLocal)) As Result
If receiverOpt Is Nothing Then
Return New Result(Nothing, Nothing)
ElseIf receiverOpt.IsLValue AndAlso receiverOpt.Type.IsReferenceType Then
......
......@@ -12487,7 +12487,7 @@ End Class
<WorkItem(745103, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/745103")>
<Fact()>
Public Sub TestCompoundOnAfieldOfGeneric()
Public Sub TestCompoundOnAFieldOfGeneric()
CompileAndVerify(
<compilation>
<file name="a.vb">
......@@ -13837,5 +13837,602 @@ End Module
]]>)
End Sub
<Fact>
Public Sub ArrayElementByReference_Invariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New String() {"b"})
End Sub
Sub F(a() As String)
G(a)
System.Console.Write(a(0))
End Sub
Sub G(a() As String)
H(a(0))
End Sub
Sub H(ByRef s As String)
s = s.ToUpper()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="B").
VerifyIL("M.G",
<![CDATA[
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "String"
IL_0007: call "Sub M.H(ByRef String)"
IL_000c: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")>
Public Sub ArrayElementByReference_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {"a"})
F(New String() {"b"})
End Sub
Sub F(a() As Object)
G(a)
System.Console.Write(a(0))
End Sub
Sub G(a() As Object)
H(a(0))
End Sub
Sub H(ByRef s As String)
s = s.ToUpper()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="AB").
VerifyIL("M.G",
<![CDATA[
{
// Code size 21 (0x15)
.maxstack 3
.locals init (String V_0)
IL_0000: ldarg.0
IL_0001: dup
IL_0002: ldc.i4.0
IL_0003: ldelem.ref
IL_0004: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToString(Object) As String"
IL_0009: stloc.0
IL_000a: ldloca.s V_0
IL_000c: call "Sub M.H(ByRef String)"
IL_0011: ldc.i4.0
IL_0012: ldloc.0
IL_0013: stelem.ref
IL_0014: ret
}
]]>)
End Sub
' Generated code results in ArrayTypeMismatchException,
' matching native compiler.
<Fact, WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")>
Public Sub ArrayElementByReferenceBase_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {"a"})
F(New String() {"b"})
End Sub
Sub F(a() As Object)
Try
G(a)
System.Console.Write(a(0))
Catch e As System.Exception
System.Console.Write(e.GetType().Name)
End Try
End Sub
Sub G(a() As Object)
H(a(0))
End Sub
Sub H(ByRef s As Object)
s = s.ToString().ToUpper()
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="AArrayTypeMismatchException").
VerifyIL("M.G",
<![CDATA[
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "Object"
IL_0007: call "Sub M.H(ByRef Object)"
IL_000c: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")>
Public Sub ArrayElementByReference_TypeParameter()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
Dim a = New String() { "b" }
Dim b = New B()
b.F(a)
System.Console.Write(a(0))
End Sub
End Module
MustInherit Class A(Of T)
Friend MustOverride Sub F(Of U As T)(a() As U)
End Class
Class B
Inherits A(Of String)
Friend Overrides Sub F(Of U As String)(a() As U)
G(a(0))
End Sub
Sub G(ByRef s As String)
s = s.ToUpper()
End Sub
End Class
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="B").
VerifyIL("B.F",
<![CDATA[
{
// Code size 42 (0x2a)
.maxstack 3
.locals init (U() V_0,
String V_1)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: ldelem "U"
IL_000a: box "U"
IL_000f: castclass "String"
IL_0014: stloc.1
IL_0015: ldloca.s V_1
IL_0017: call "Sub B.G(ByRef String)"
IL_001c: ldloc.0
IL_001d: ldc.i4.0
IL_001e: ldloc.1
IL_001f: unbox.any "U"
IL_0024: stelem "U"
IL_0029: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")>
Public Sub ArrayElementByReference_StructConstraint()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
Dim a = New Integer() { 1 }
Dim b = New B()
b.F(a)
System.Console.Write(a(0))
End Sub
End Module
MustInherit Class A(Of T)
Friend MustOverride Sub F(Of U As {T, Structure})(a() As U)
End Class
Class B
Inherits A(Of Integer)
Friend Overrides Sub F(Of U As {Integer, Structure})(a() As U)
G(a(0))
End Sub
Sub G(ByRef i As Integer)
i += 1
End Sub
End Class
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="2").
VerifyIL("B.F",
<![CDATA[
{
// Code size 47 (0x2f)
.maxstack 3
.locals init (U() V_0,
Integer V_1)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: ldelem "U"
IL_000a: box "U"
IL_000f: unbox.any "Integer"
IL_0014: stloc.1
IL_0015: ldloca.s V_1
IL_0017: call "Sub B.G(ByRef Integer)"
IL_001c: ldloc.0
IL_001d: ldc.i4.0
IL_001e: ldloc.1
IL_001f: box "Integer"
IL_0024: unbox.any "U"
IL_0029: stelem "U"
IL_002e: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementByReference_ValueType()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Integer() {1})
End Sub
Sub F(a() As Integer)
G(a)
System.Console.Write(a(0))
End Sub
Sub G(a() As Integer)
H(a(0))
End Sub
Sub H(ByRef i As Integer)
i = 2
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="2").
VerifyIL("M.G",
<![CDATA[
{
// Code size 13 (0xd)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "Integer"
IL_0007: call "Sub M.H(ByRef Integer)"
IL_000c: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementCompoundAssignment_Invariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New String() {""}, "B")
End Sub
Sub F(a() As String, s As String)
G(a, s)
System.Console.Write(a(0))
End Sub
Sub G(a() As String, s As String)
a(0) += s
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="B").
VerifyIL("M.G",
<![CDATA[
{
// Code size 19 (0x13)
.maxstack 3
.locals init (String& V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "String"
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldind.ref
IL_000b: ldarg.1
IL_000c: call "Function String.Concat(String, String) As String"
IL_0011: stind.ref
IL_0012: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")>
Public Sub ArrayElementCompoundAssignment_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {""}, "A")
F(New String() {""}, "B")
End Sub
Sub F(a() As Object, s As String)
G(a, s)
System.Console.Write(a(0))
End Sub
Sub G(a() As Object, s As String)
a(0) += s
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="AB").
VerifyIL("M.G",
<![CDATA[
{
// Code size 15 (0xf)
.maxstack 4
.locals init (Object() V_0)
IL_0000: ldarg.0
IL_0001: dup
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: ldloc.0
IL_0005: ldc.i4.0
IL_0006: ldelem.ref
IL_0007: ldarg.1
IL_0008: call "Function Microsoft.VisualBasic.CompilerServices.Operators.AddObject(Object, Object) As Object"
IL_000d: stelem.ref
IL_000e: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementCompoundAssignment_ValueType()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Integer() {1}, 2)
End Sub
Sub F(a() As Integer, i As Integer)
G(a, i)
System.Console.Write(a(0))
End Sub
Sub G(a() As Integer, i As Integer)
a(0) += i
End Sub
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="3").
VerifyIL("M.G",
<![CDATA[
{
// Code size 15 (0xf)
.maxstack 3
.locals init (Integer& V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "Integer"
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldind.i4
IL_000b: ldarg.1
IL_000c: add.ovf
IL_000d: stind.i4
IL_000e: ret
}
]]>)
End Sub
<Fact, WorkItem(547533, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=547533")>
Public Sub ArrayElementCompoundAssignment_Covariant_NonConstantIndex()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {""}, "A")
F(New String() {""}, "B")
End Sub
Sub F(a() As Object, s As String)
G(a, s)
System.Console.Write(a(0))
End Sub
Sub G(a() As Object, s As String)
a(Index(a)) += s
End Sub
Function Index(arg As Object) As Integer
System.Console.Write(arg.GetType().Name)
Return 0
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="Object[]AString[]B").
VerifyIL("M.G",
<![CDATA[
{
// Code size 22 (0x16)
.maxstack 4
.locals init (Object() V_0,
Integer V_1)
IL_0000: ldarg.0
IL_0001: dup
IL_0002: stloc.0
IL_0003: ldarg.0
IL_0004: call "Function M.Index(Object) As Integer"
IL_0009: dup
IL_000a: stloc.1
IL_000b: ldloc.0
IL_000c: ldloc.1
IL_000d: ldelem.ref
IL_000e: ldarg.1
IL_000f: call "Function Microsoft.VisualBasic.CompilerServices.Operators.AddObject(Object, Object) As Object"
IL_0014: stelem.ref
IL_0015: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementWithBlock_Invariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New String() {"B"})
End Sub
Sub F(a() As String)
System.Console.Write(G(a))
End Sub
Function G(a() As String) As String
With a(0)
Return .ToString() + .ToLower()
End With
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="Bb").
VerifyIL("M.G",
<![CDATA[
{
// Code size 22 (0x16)
.maxstack 2
.locals init (String V_0) //$W0
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelem.ref
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: callvirt "Function String.ToString() As String"
IL_000a: ldloc.0
IL_000b: callvirt "Function String.ToLower() As String"
IL_0010: call "Function String.Concat(String, String) As String"
IL_0015: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementWithBlock_Covariant()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Object() {"A"})
F(New String() {"B"})
End Sub
Sub F(a() As Object)
System.Console.Write(G(a))
End Sub
Function G(a() As Object) As String
With a(0)
Return .ToString() + .ToLower()
End With
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="AaBb").
VerifyIL("M.G",
<![CDATA[
{
// Code size 42 (0x2a)
.maxstack 8
.locals init (Object V_0) //$W0
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelem.ref
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: callvirt "Function Object.ToString() As String"
IL_000a: ldloc.0
IL_000b: ldnull
IL_000c: ldstr "ToLower"
IL_0011: ldc.i4.0
IL_0012: newarr "Object"
IL_0017: ldnull
IL_0018: ldnull
IL_0019: ldnull
IL_001a: call "Function Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object, System.Type, String, Object(), String(), System.Type(), Boolean()) As Object"
IL_001f: call "Function Microsoft.VisualBasic.CompilerServices.Operators.AddObject(Object, Object) As Object"
IL_0024: call "Function Microsoft.VisualBasic.CompilerServices.Conversions.ToString(Object) As String"
IL_0029: ret
}
]]>)
End Sub
<Fact>
Public Sub ArrayElementWithBlock_ValueType()
Dim comp =
<compilation>
<file>
Option Strict Off
Module M
Sub Main()
F(New Integer() {1})
End Sub
Sub F(a() As Integer)
System.Console.Write(G(a))
End Sub
Function G(a() As Integer) As String
With a(0)
Return .ToString() + .ToString()
End With
End Function
End Module
</file>
</compilation>
CompileAndVerify(comp, expectedOutput:="11").
VerifyIL("M.G",
<![CDATA[
{
// Code size 26 (0x1a)
.maxstack 2
.locals init (Integer& V_0) //$W0
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "Integer"
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: call "Function Integer.ToString() As String"
IL_000e: ldloc.0
IL_000f: call "Function Integer.ToString() As String"
IL_0014: call "Function String.Concat(String, String) As String"
IL_0019: ret
}
]]>)
End Sub
End Class
End Namespace
......@@ -1465,25 +1465,29 @@ Position set for item 'Goo'
verifier.VerifyIL("Program.Shift",
<![CDATA[
{
// Code size 46 (0x2e)
// Code size 56 (0x38)
.maxstack 4
.locals init (T& V_0)
.locals init (T() V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "T"
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: constrained. "T"
IL_0010: callvirt "Function IMoveable.get_Position() As Integer"
IL_0015: ldarg.0
IL_0016: ldc.i4.0
IL_0017: ldelema "T"
IL_001c: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_0021: add.ovf
IL_0022: constrained. "T"
IL_0028: callvirt "Sub IMoveable.set_Position(Integer)"
IL_002d: ret
IL_0001: dup
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: readonly.
IL_0006: ldelema "T"
IL_000b: ldloc.0
IL_000c: ldc.i4.0
IL_000d: readonly.
IL_000f: ldelema "T"
IL_0014: constrained. "T"
IL_001a: callvirt "Function IMoveable.get_Position() As Integer"
IL_001f: ldarg.0
IL_0020: ldc.i4.0
IL_0021: ldelema "T"
IL_0026: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_002b: add.ovf
IL_002c: constrained. "T"
IL_0032: callvirt "Sub IMoveable.set_Position(Integer)"
IL_0037: ret
}
]]>)
......@@ -1499,27 +1503,31 @@ Position set for item 'Bar'
verifier.VerifyIL("Program.Shift",
<![CDATA[
{
// Code size 48 (0x30)
// Code size 58 (0x3a)
.maxstack 4
.locals init (T& V_0)
.locals init (T() V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: ldelema "T"
IL_0008: dup
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: constrained. "T"
IL_0011: callvirt "Function IMoveable.get_Position() As Integer"
IL_0016: ldarg.0
IL_0017: ldc.i4.0
IL_0018: ldelema "T"
IL_001d: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_0022: add.ovf
IL_0023: constrained. "T"
IL_0029: callvirt "Sub IMoveable.set_Position(Integer)"
IL_002e: nop
IL_002f: ret
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: readonly.
IL_0007: ldelema "T"
IL_000c: ldloc.0
IL_000d: ldc.i4.0
IL_000e: readonly.
IL_0010: ldelema "T"
IL_0015: constrained. "T"
IL_001b: callvirt "Function IMoveable.get_Position() As Integer"
IL_0020: ldarg.0
IL_0021: ldc.i4.0
IL_0022: ldelema "T"
IL_0027: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_002c: add.ovf
IL_002d: constrained. "T"
IL_0033: callvirt "Sub IMoveable.set_Position(Integer)"
IL_0038: nop
IL_0039: ret
}
]]>)
End Sub
......@@ -2122,25 +2130,29 @@ Position set for item 'Goo'
verifier.VerifyIL("Program.Shift",
<![CDATA[
{
// Code size 46 (0x2e)
// Code size 56 (0x38)
.maxstack 4
.locals init (T& V_0)
.locals init (T() V_0)
IL_0000: ldarg.0
IL_0001: ldc.i4.0
IL_0002: ldelema "T"
IL_0007: dup
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: constrained. "T"
IL_0010: callvirt "Function IMoveable.get_Position() As Integer"
IL_0015: ldarg.0
IL_0016: ldc.i4.0
IL_0017: ldelema "T"
IL_001c: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_0021: add.ovf
IL_0022: constrained. "T"
IL_0028: callvirt "Sub IMoveable.set_Position(Integer)"
IL_002d: ret
IL_0001: dup
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: readonly.
IL_0006: ldelema "T"
IL_000b: ldloc.0
IL_000c: ldc.i4.0
IL_000d: readonly.
IL_000f: ldelema "T"
IL_0014: constrained. "T"
IL_001a: callvirt "Function IMoveable.get_Position() As Integer"
IL_001f: ldarg.0
IL_0020: ldc.i4.0
IL_0021: ldelema "T"
IL_0026: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_002b: add.ovf
IL_002c: constrained. "T"
IL_0032: callvirt "Sub IMoveable.set_Position(Integer)"
IL_0037: ret
}
]]>)
......@@ -2156,27 +2168,31 @@ Position set for item 'Bar'
verifier.VerifyIL("Program.Shift",
<![CDATA[
{
// Code size 48 (0x30)
// Code size 58 (0x3a)
.maxstack 4
.locals init (T& V_0)
.locals init (T() V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: ldelema "T"
IL_0008: dup
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: constrained. "T"
IL_0011: callvirt "Function IMoveable.get_Position() As Integer"
IL_0016: ldarg.0
IL_0017: ldc.i4.0
IL_0018: ldelema "T"
IL_001d: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_0022: add.ovf
IL_0023: constrained. "T"
IL_0029: callvirt "Sub IMoveable.set_Position(Integer)"
IL_002e: nop
IL_002f: ret
IL_0002: dup
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: readonly.
IL_0007: ldelema "T"
IL_000c: ldloc.0
IL_000d: ldc.i4.0
IL_000e: readonly.
IL_0010: ldelema "T"
IL_0015: constrained. "T"
IL_001b: callvirt "Function IMoveable.get_Position() As Integer"
IL_0020: ldarg.0
IL_0021: ldc.i4.0
IL_0022: ldelema "T"
IL_0027: call "Function Program.GetOffset(Of T)(ByRef T) As Integer"
IL_002c: add.ovf
IL_002d: constrained. "T"
IL_0033: callvirt "Sub IMoveable.set_Position(Integer)"
IL_0038: nop
IL_0039: ret
}
]]>)
End Sub
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册