提交 3e9297b7 编写于 作者: A Andy Gocke

Generate fake indexer code for arrays

Generates fake indexers for arrays that take System.Index and
System.Range.
上级 3a342120
......@@ -6804,7 +6804,13 @@ private BoundExpression BindArrayAccess(ExpressionSyntax node, BoundExpression e
}
}
return new BoundArrayAccess(node, expr, convertedArguments.AsImmutableOrNull(), arrayType.ElementType.TypeSymbol, hasErrors);
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
var resultType = rank == 1 &&
convertedArguments[0].Type == GetWellKnownType(WellKnownType.System_Range, ref useSiteDiagnostics)
? arrayType
: arrayType.ElementType.TypeSymbol;
return new BoundArrayAccess(node, expr, convertedArguments.AsImmutableOrNull(), resultType, hasErrors);
}
private BoundExpression ConvertToArrayIndex(BoundExpression index, SyntaxNode node, DiagnosticBag diagnostics)
......@@ -6824,7 +6830,9 @@ private BoundExpression ConvertToArrayIndex(BoundExpression index, SyntaxNode no
TryImplicitConversionToArrayIndex(index, SpecialType.System_Int32, node, diagnostics) ??
TryImplicitConversionToArrayIndex(index, SpecialType.System_UInt32, node, diagnostics) ??
TryImplicitConversionToArrayIndex(index, SpecialType.System_Int64, node, diagnostics) ??
TryImplicitConversionToArrayIndex(index, SpecialType.System_UInt64, node, diagnostics);
TryImplicitConversionToArrayIndex(index, SpecialType.System_UInt64, node, diagnostics) ??
TryImplicitConversionToArrayIndex(index, WellKnownType.System_Index, node, diagnostics) ??
TryImplicitConversionToArrayIndex(index, WellKnownType.System_Range, node, diagnostics);
if (result == null)
{
......@@ -6842,21 +6850,53 @@ private BoundExpression ConvertToArrayIndex(BoundExpression index, SyntaxNode no
return result;
}
private BoundExpression TryImplicitConversionToArrayIndex(BoundExpression expr, WellKnownType wellKnownType, SyntaxNode node, DiagnosticBag diagnostics)
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
TypeSymbol type = GetWellKnownType(wellKnownType, ref useSiteDiagnostics);
if (!type.IsErrorType())
{
var attemptDiagnostics = DiagnosticBag.GetInstance();
var result = TryImplicitConversionToArrayIndex(expr, type, node, attemptDiagnostics);
if (!(result is null))
{
diagnostics.AddRange(attemptDiagnostics);
}
attemptDiagnostics.Free();
return result;
}
return null;
}
private BoundExpression TryImplicitConversionToArrayIndex(BoundExpression expr, SpecialType specialType, SyntaxNode node, DiagnosticBag diagnostics)
{
DiagnosticBag attemptDiagnostics = DiagnosticBag.GetInstance();
TypeSymbol type = GetSpecialType(specialType, attemptDiagnostics, node);
var result = TryImplicitConversionToArrayIndex(expr, type, node, attemptDiagnostics);
if (!(result is null))
{
diagnostics.AddRange(attemptDiagnostics);
}
attemptDiagnostics.Free();
return result;
}
private BoundExpression TryImplicitConversionToArrayIndex(BoundExpression expr, TypeSymbol targetType, SyntaxNode node, DiagnosticBag diagnostics)
{
Debug.Assert(expr != null);
Debug.Assert((object)type != null);
Debug.Assert((object)targetType != null);
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
Conversion conversion = this.Conversions.ClassifyImplicitConversionFromExpression(expr, type, ref useSiteDiagnostics);
Conversion conversion = this.Conversions.ClassifyImplicitConversionFromExpression(expr, targetType, ref useSiteDiagnostics);
diagnostics.Add(node, useSiteDiagnostics);
if (!conversion.Exists)
{
attemptDiagnostics.Free();
return null;
}
......@@ -6865,12 +6905,9 @@ private BoundExpression TryImplicitConversionToArrayIndex(BoundExpression expr,
conversion = conversion.SetArrayIndexConversionForDynamic();
}
BoundExpression result = CreateConversion(expr.Syntax, expr, conversion, isCast: false, conversionGroupOpt: null, destination: type, diagnostics: attemptDiagnostics); // UNDONE: was cast?
BoundExpression result = CreateConversion(expr.Syntax, expr, conversion, isCast: false, conversionGroupOpt: null, destination: targetType, diagnostics); // UNDONE: was cast?
Debug.Assert(result != null); // If this ever fails (it shouldn't), then put a null-check around the diagnostics update.
diagnostics.AddRange(attemptDiagnostics);
attemptDiagnostics.Free();
return result;
}
......
......@@ -1356,7 +1356,16 @@ public override BoundNode VisitArrayAccess(BoundArrayAccess node)
VisitRvalue(i);
}
_resultType = type?.ElementType ?? default;
if (node.Indices.Length == 1 &&
node.Indices[0].Type == compilation.GetWellKnownType(WellKnownType.System_Range))
{
_resultType = TypeSymbolWithAnnotations.Create(type);
}
else
{
_resultType = type?.ElementType ?? default;
}
return null;
}
......
......@@ -525,6 +525,141 @@ public override BoundNode VisitTypeOrInstanceInitializers(BoundTypeOrInstanceIni
return new BoundStatementList(node.Syntax, rewrittenStatements, node.HasErrors);
}
public override BoundNode VisitArrayAccess(BoundArrayAccess node)
{
// If the array access index is of type System.Index or System.Range
// we need to translate it into a call into an actual indexer, instead
// of a simple array element access.
if (this.EmitModule is null ||
node.Indices.Length != 1 ||
node.Indices[0].Type.SpecialType != SpecialType.None)
{
return base.VisitArrayAccess(node);
}
// PROTOTYPE: THIS MUST BE REMOVED BEFORE DEV16
// Since it takes a long time to update mscorlib we fake up the right
// code to pretend there are two indexers that support Index and Range
// on arrays.
var syntax = node.Syntax;
var F = _factory;
var indexLocal = F.StoreToTemp(
VisitExpression(node.Indices[0]),
out BoundAssignmentOperator indexAssign);
var arrayLocal = F.StoreToTemp(
VisitExpression(node.Expression),
out BoundAssignmentOperator arrayAssign);
var indexType = VisitType(node.Indices[0].Type);
if (!TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Index__Value, out PropertySymbol indexValueSymbol) ||
!TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Index__FromEnd, out PropertySymbol indexFromEndSymbol))
{
return node;
}
BoundExpression resultExpr;
if (indexType == _compilation.GetWellKnownType(WellKnownType.System_Index))
{
// array[Index] is translated to:
// index.FromEnd ? array[array.Length - index.Value] : array[index.Value]
var indexValueExpr = F.Property(indexLocal, indexValueSymbol);
resultExpr = F.Sequence(
ImmutableArray.Create<LocalSymbol>(
indexLocal.LocalSymbol,
arrayLocal.LocalSymbol),
ImmutableArray.Create<BoundExpression>(
indexAssign,
arrayAssign),
F.Conditional(
F.Property(indexLocal, indexFromEndSymbol),
F.ArrayAccess(arrayLocal, ImmutableArray.Create<BoundExpression>(F.Binary(
BinaryOperatorKind.Subtraction,
F.SpecialType(SpecialType.System_Int32),
F.ArrayLength(arrayLocal),
indexValueExpr))),
F.ArrayAccess(arrayLocal, ImmutableArray.Create(indexValueExpr)),
node.Type));
}
else if (indexType == _compilation.GetWellKnownType(WellKnownType.System_Range))
{
// array[Range] is translated to:
// var start = range.Start.FromEnd ? array.Length - range.Start.Value : range.Start.Value;
// var end = range.End.FromEnd ? array.Length - range.End.Value : range.End.Value;
// var length = end - start;
// var newArr = new T[length];
// Array.Copy(array, start, newArr, 0, length);
// push newArray
if (!TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Range__Start, out PropertySymbol rangeStartSymbol) ||
!TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Range__End, out PropertySymbol rangeEndSymbol) ||
!TryGetWellKnownTypeMember(syntax, WellKnownMember.System_Array__Copy, out MethodSymbol arrayCopySymbol))
{
return node;
}
var startLocal = F.StoreToTemp(
F.Conditional(
F.Property(F.Property(indexLocal, rangeStartSymbol), indexFromEndSymbol),
F.Binary(
BinaryOperatorKind.Subtraction,
F.SpecialType(SpecialType.System_Int32),
F.ArrayLength(arrayLocal),
F.Property(F.Property(indexLocal, rangeEndSymbol), indexValueSymbol)),
F.Property(F.Property(indexLocal, rangeStartSymbol), indexValueSymbol),
F.SpecialType(SpecialType.System_Int32)),
out BoundAssignmentOperator startAssign);
var endLocal = F.StoreToTemp(
F.Conditional(
F.Property(F.Property(indexLocal, rangeEndSymbol), indexFromEndSymbol),
F.Binary(
BinaryOperatorKind.Subtraction,
F.SpecialType(SpecialType.System_Int32),
F.ArrayLength(arrayLocal),
F.Property(F.Property(indexLocal, rangeEndSymbol), indexValueSymbol)),
F.Property(F.Property(indexLocal, rangeEndSymbol), indexValueSymbol),
F.SpecialType(SpecialType.System_Int32)),
out BoundAssignmentOperator endAssign);
var lengthLocal = F.StoreToTemp(
F.Binary(BinaryOperatorKind.Subtraction, F.SpecialType(SpecialType.System_Int32), endLocal, startLocal),
out BoundAssignmentOperator lengthAssign);
var elementType = ((ArrayTypeSymbol)node.Type).ElementType.TypeSymbol;
var newArrLocal = F.StoreToTemp(F.Array(elementType, lengthLocal), out BoundAssignmentOperator newArrAssign);
var copyExpr = F.Call(null, arrayCopySymbol, ImmutableArray.Create<BoundExpression>(
arrayLocal,
startLocal,
newArrLocal,
F.Literal(0),
lengthLocal));
resultExpr = F.Sequence(
ImmutableArray.Create(
indexLocal.LocalSymbol,
arrayLocal.LocalSymbol,
startLocal.LocalSymbol,
endLocal.LocalSymbol,
lengthLocal.LocalSymbol,
newArrLocal.LocalSymbol),
ImmutableArray.Create<BoundExpression>(
indexAssign,
arrayAssign,
startAssign,
endAssign,
lengthAssign,
newArrAssign,
copyExpr),
newArrLocal);
}
else
{
throw ExceptionUtilities.Unreachable;
}
return resultExpr;
}
internal static bool IsFieldOrPropertyInitializer(BoundStatement initializer)
{
var syntax = initializer.Syntax;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
public class IndexAndRangeTests : CSharpTestBase
{
[Fact]
public void FakeIndexIndexerArray()
{
var comp = CreateCompilationWithIndex(@"
using System;
class C
{
public static void Main()
{
var x = new[] { 1, 2, 3, 11 };
M(x);
}
public static void M(int[] array)
{
Console.WriteLine(array[new Index(1, false)]);
Console.WriteLine(array[^1]);
}
}", TestOptions.ReleaseExe);
var verifier = CompileAndVerify(comp, expectedOutput: @"2
11");
verifier.VerifyIL("C.M", @"
{
// Code size 99 (0x63)
.maxstack 3
.locals init (System.Index V_0,
int[] V_1)
IL_0000: ldloca.s V_0
IL_0002: ldc.i4.1
IL_0003: ldc.i4.0
IL_0004: call ""System.Index..ctor(int, bool)""
IL_0009: ldarg.0
IL_000a: stloc.1
IL_000b: ldloca.s V_0
IL_000d: call ""bool System.Index.FromEnd.get""
IL_0012: brtrue.s IL_001f
IL_0014: ldloc.1
IL_0015: ldloca.s V_0
IL_0017: call ""int System.Index.Value.get""
IL_001c: ldelem.i4
IL_001d: br.s IL_002c
IL_001f: ldloc.1
IL_0020: ldloc.1
IL_0021: ldlen
IL_0022: conv.i4
IL_0023: ldloca.s V_0
IL_0025: call ""int System.Index.Value.get""
IL_002a: sub
IL_002b: ldelem.i4
IL_002c: call ""void System.Console.WriteLine(int)""
IL_0031: ldloca.s V_0
IL_0033: ldc.i4.1
IL_0034: ldc.i4.1
IL_0035: call ""System.Index..ctor(int, bool)""
IL_003a: ldarg.0
IL_003b: stloc.1
IL_003c: ldloca.s V_0
IL_003e: call ""bool System.Index.FromEnd.get""
IL_0043: brtrue.s IL_0050
IL_0045: ldloc.1
IL_0046: ldloca.s V_0
IL_0048: call ""int System.Index.Value.get""
IL_004d: ldelem.i4
IL_004e: br.s IL_005d
IL_0050: ldloc.1
IL_0051: ldloc.1
IL_0052: ldlen
IL_0053: conv.i4
IL_0054: ldloca.s V_0
IL_0056: call ""int System.Index.Value.get""
IL_005b: sub
IL_005c: ldelem.i4
IL_005d: call ""void System.Console.WriteLine(int)""
IL_0062: ret
}");
}
[Fact]
public void FakeIndexIndexerArrayNoValue()
{
var comp = CreateCompilation(@"
using System;
namespace System
{
public readonly struct Index
{
private readonly int _value;
//public int Value => _value < 0 ? ~_value : _value;
public bool FromEnd => _value < 0;
public Index(int value, bool fromEnd)
{
if (value < 0)
{
throw new ArgumentException(""Index must not be negative."", nameof(value));
}
_value = fromEnd? ~value : value;
}
public static implicit operator Index(int value) => new Index(value, fromEnd: false);
}
}
class C
{
public static void Main()
{
var x = new[] { 11 };
Console.WriteLine(x[^1]);
}
}", options: TestOptions.ReleaseExe);
comp.VerifyDiagnostics();
// We check for the well-known member in lowering, so you won't normally see this
// error during binding. This is fine for a preview-only feature.
comp.VerifyEmitDiagnostics(
// (30,27): error CS0656: Missing compiler required member 'System.Index.Value'
// Console.WriteLine(x[^1]);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "x[^1]").WithArguments("System.Index", "Value").WithLocation(30, 27));
}
[Fact]
public void FakeRangeIndexerArray()
{
var comp = CreateCompilationWithIndexAndRange(@"
using System;
class C
{
public static void Main()
{
var arr = new[] { 1, 2, 3, 11 };
var result = M(arr);
Console.WriteLine(result.Length);
foreach (var x in result)
{
Console.WriteLine(x);
}
}
public static int[] M(int[] array) => array[1..3];
}", TestOptions.ReleaseExe);
var verifier = CompileAndVerify(comp, verify: Verification.Passes, expectedOutput: @"2
2
3");
verifier.VerifyIL("C.M", @"
{
// Code size 158 (0x9e)
.maxstack 5
.locals init (System.Range V_0,
int[] V_1,
int V_2,
int V_3,
int[] V_4,
System.Index V_5)
IL_0000: ldc.i4.1
IL_0001: call ""System.Index System.Index.op_Implicit(int)""
IL_0006: ldc.i4.3
IL_0007: call ""System.Index System.Index.op_Implicit(int)""
IL_000c: call ""System.Range System.Range.Create(System.Index, System.Index)""
IL_0011: stloc.0
IL_0012: ldarg.0
IL_0013: stloc.1
IL_0014: ldloca.s V_0
IL_0016: call ""System.Index System.Range.Start.get""
IL_001b: stloc.s V_5
IL_001d: ldloca.s V_5
IL_001f: call ""bool System.Index.FromEnd.get""
IL_0024: brtrue.s IL_0038
IL_0026: ldloca.s V_0
IL_0028: call ""System.Index System.Range.Start.get""
IL_002d: stloc.s V_5
IL_002f: ldloca.s V_5
IL_0031: call ""int System.Index.Value.get""
IL_0036: br.s IL_004c
IL_0038: ldloc.1
IL_0039: ldlen
IL_003a: conv.i4
IL_003b: ldloca.s V_0
IL_003d: call ""System.Index System.Range.End.get""
IL_0042: stloc.s V_5
IL_0044: ldloca.s V_5
IL_0046: call ""int System.Index.Value.get""
IL_004b: sub
IL_004c: stloc.2
IL_004d: ldloca.s V_0
IL_004f: call ""System.Index System.Range.End.get""
IL_0054: stloc.s V_5
IL_0056: ldloca.s V_5
IL_0058: call ""bool System.Index.FromEnd.get""
IL_005d: brtrue.s IL_0071
IL_005f: ldloca.s V_0
IL_0061: call ""System.Index System.Range.End.get""
IL_0066: stloc.s V_5
IL_0068: ldloca.s V_5
IL_006a: call ""int System.Index.Value.get""
IL_006f: br.s IL_0085
IL_0071: ldloc.1
IL_0072: ldlen
IL_0073: conv.i4
IL_0074: ldloca.s V_0
IL_0076: call ""System.Index System.Range.End.get""
IL_007b: stloc.s V_5
IL_007d: ldloca.s V_5
IL_007f: call ""int System.Index.Value.get""
IL_0084: sub
IL_0085: ldloc.2
IL_0086: sub
IL_0087: stloc.3
IL_0088: ldloc.3
IL_0089: newarr ""int""
IL_008e: stloc.s V_4
IL_0090: ldloc.1
IL_0091: ldloc.2
IL_0092: ldloc.s V_4
IL_0094: ldc.i4.0
IL_0095: ldloc.3
IL_0096: call ""void System.Array.Copy(System.Array, int, System.Array, int, int)""
IL_009b: ldloc.s V_4
IL_009d: ret
}
");
}
[Fact]
public void FakeRangeToEndIndexerArray()
{
var comp = CreateCompilationWithIndexAndRange(@"
using System;
class C
{
public static void Main()
{
var arr = new[] { 1, 2, 3, 11 };
var result = M(arr);
Console.WriteLine(result.Length);
foreach (var x in result)
{
Console.WriteLine(x);
}
}
public static int[] M(int[] array) => array[1..];
}", TestOptions.ReleaseExe);
var verifier = CompileAndVerify(comp, verify: Verification.Passes, expectedOutput: @"3
2
3
11");
verifier.VerifyIL("C.M", @"
{
// Code size 152 (0x98)
.maxstack 5
.locals init (System.Range V_0,
int[] V_1,
int V_2,
int V_3,
int[] V_4,
System.Index V_5)
IL_0000: ldc.i4.1
IL_0001: call ""System.Index System.Index.op_Implicit(int)""
IL_0006: call ""System.Range System.Range.FromStart(System.Index)""
IL_000b: stloc.0
IL_000c: ldarg.0
IL_000d: stloc.1
IL_000e: ldloca.s V_0
IL_0010: call ""System.Index System.Range.Start.get""
IL_0015: stloc.s V_5
IL_0017: ldloca.s V_5
IL_0019: call ""bool System.Index.FromEnd.get""
IL_001e: brtrue.s IL_0032
IL_0020: ldloca.s V_0
IL_0022: call ""System.Index System.Range.Start.get""
IL_0027: stloc.s V_5
IL_0029: ldloca.s V_5
IL_002b: call ""int System.Index.Value.get""
IL_0030: br.s IL_0046
IL_0032: ldloc.1
IL_0033: ldlen
IL_0034: conv.i4
IL_0035: ldloca.s V_0
IL_0037: call ""System.Index System.Range.End.get""
IL_003c: stloc.s V_5
IL_003e: ldloca.s V_5
IL_0040: call ""int System.Index.Value.get""
IL_0045: sub
IL_0046: stloc.2
IL_0047: ldloca.s V_0
IL_0049: call ""System.Index System.Range.End.get""
IL_004e: stloc.s V_5
IL_0050: ldloca.s V_5
IL_0052: call ""bool System.Index.FromEnd.get""
IL_0057: brtrue.s IL_006b
IL_0059: ldloca.s V_0
IL_005b: call ""System.Index System.Range.End.get""
IL_0060: stloc.s V_5
IL_0062: ldloca.s V_5
IL_0064: call ""int System.Index.Value.get""
IL_0069: br.s IL_007f
IL_006b: ldloc.1
IL_006c: ldlen
IL_006d: conv.i4
IL_006e: ldloca.s V_0
IL_0070: call ""System.Index System.Range.End.get""
IL_0075: stloc.s V_5
IL_0077: ldloca.s V_5
IL_0079: call ""int System.Index.Value.get""
IL_007e: sub
IL_007f: ldloc.2
IL_0080: sub
IL_0081: stloc.3
IL_0082: ldloc.3
IL_0083: newarr ""int""
IL_0088: stloc.s V_4
IL_008a: ldloc.1
IL_008b: ldloc.2
IL_008c: ldloc.s V_4
IL_008e: ldc.i4.0
IL_008f: ldloc.3
IL_0090: call ""void System.Array.Copy(System.Array, int, System.Array, int, int)""
IL_0095: ldloc.s V_4
IL_0097: ret
}
");
}
[Fact]
public void FakeRangeFromStartIndexerArray()
{
var comp = CreateCompilationWithIndexAndRange(@"
using System;
class C
{
public static void Main()
{
var arr = new[] { 1, 2, 3, 11 };
var result = M(arr);
Console.WriteLine(result.Length);
foreach (var x in result)
{
Console.WriteLine(x);
}
}
public static int[] M(int[] array) => array[..3];
}", TestOptions.ReleaseExe);
var verifier = CompileAndVerify(comp, verify: Verification.Passes, expectedOutput: @"3
1
2
3");
verifier.VerifyIL("C.M", @"
{
// Code size 152 (0x98)
.maxstack 5
.locals init (System.Range V_0,
int[] V_1,
int V_2,
int V_3,
int[] V_4,
System.Index V_5)
IL_0000: ldc.i4.3
IL_0001: call ""System.Index System.Index.op_Implicit(int)""
IL_0006: call ""System.Range System.Range.ToEnd(System.Index)""
IL_000b: stloc.0
IL_000c: ldarg.0
IL_000d: stloc.1
IL_000e: ldloca.s V_0
IL_0010: call ""System.Index System.Range.Start.get""
IL_0015: stloc.s V_5
IL_0017: ldloca.s V_5
IL_0019: call ""bool System.Index.FromEnd.get""
IL_001e: brtrue.s IL_0032
IL_0020: ldloca.s V_0
IL_0022: call ""System.Index System.Range.Start.get""
IL_0027: stloc.s V_5
IL_0029: ldloca.s V_5
IL_002b: call ""int System.Index.Value.get""
IL_0030: br.s IL_0046
IL_0032: ldloc.1
IL_0033: ldlen
IL_0034: conv.i4
IL_0035: ldloca.s V_0
IL_0037: call ""System.Index System.Range.End.get""
IL_003c: stloc.s V_5
IL_003e: ldloca.s V_5
IL_0040: call ""int System.Index.Value.get""
IL_0045: sub
IL_0046: stloc.2
IL_0047: ldloca.s V_0
IL_0049: call ""System.Index System.Range.End.get""
IL_004e: stloc.s V_5
IL_0050: ldloca.s V_5
IL_0052: call ""bool System.Index.FromEnd.get""
IL_0057: brtrue.s IL_006b
IL_0059: ldloca.s V_0
IL_005b: call ""System.Index System.Range.End.get""
IL_0060: stloc.s V_5
IL_0062: ldloca.s V_5
IL_0064: call ""int System.Index.Value.get""
IL_0069: br.s IL_007f
IL_006b: ldloc.1
IL_006c: ldlen
IL_006d: conv.i4
IL_006e: ldloca.s V_0
IL_0070: call ""System.Index System.Range.End.get""
IL_0075: stloc.s V_5
IL_0077: ldloca.s V_5
IL_0079: call ""int System.Index.Value.get""
IL_007e: sub
IL_007f: ldloc.2
IL_0080: sub
IL_0081: stloc.3
IL_0082: ldloc.3
IL_0083: newarr ""int""
IL_0088: stloc.s V_4
IL_008a: ldloc.1
IL_008b: ldloc.2
IL_008c: ldloc.s V_4
IL_008e: ldc.i4.0
IL_008f: ldloc.3
IL_0090: call ""void System.Array.Copy(System.Array, int, System.Array, int, int)""
IL_0095: ldloc.s V_4
IL_0097: ret
}
");
}
[Fact]
public void LowerIndex_Int()
{
......
......@@ -10,6 +10,7 @@ internal enum WellKnownMember
System_Array__get_Length,
System_Array__Empty,
System_Array__Copy,
System_Convert__ToBooleanDecimal,
System_Convert__ToBooleanInt32,
......@@ -447,6 +448,10 @@ internal enum WellKnownMember
Microsoft_CodeAnalysis_EmbeddedAttribute__ctor,
System_Index__ctor,
System_Index__FromEnd,
System_Index__Value,
System_Range__Start,
System_Range__End,
System_Range__Create,
System_Range__ToEnd,
System_Range__FromStart,
......
......@@ -45,6 +45,18 @@ static WellKnownMembers()
0, // Method Signature
(byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.GenericMethodParameter, 0, // Return Type
// System_Array__Copy
(byte)(MemberFlags.Method | MemberFlags.Static), // Flags
(byte)WellKnownType.System_Array, // DeclaringTypeId
0, // Arity
5, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, // Return Type
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Array,
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32,
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Array,
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32,
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32,
// System_Convert__ToBooleanDecimal
(byte)(MemberFlags.Method | MemberFlags.Static), // Flags
(byte)WellKnownType.System_Convert, // DeclaringTypeId
......@@ -3062,6 +3074,34 @@ static WellKnownMembers()
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32,
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Boolean,
// System_Index__FromEnd
(byte)(MemberFlags.Property), // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Index - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Boolean, // Return Type
// System_Index__Value
(byte)(MemberFlags.Property), // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Index - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, // Return type
// System_Range__Start
(byte)MemberFlags.Property, // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Range - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Index - WellKnownType.ExtSentinel), // Return Type: System.Index
// System_Range__End
(byte)MemberFlags.Property, // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Range - WellKnownType.ExtSentinel), // DeclaringTypeId
0, // Arity
0, // Method Signature
(byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Index - WellKnownType.ExtSentinel), // Return Type: System.Index
// System_Range__Create
(byte)(MemberFlags.Method | MemberFlags.Static), // Flags
(byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Range - WellKnownType.ExtSentinel), // DeclaringTypeId
......@@ -3265,6 +3305,7 @@ static WellKnownMembers()
"Pow", // System_Math__PowDoubleDouble
"get_Length", // System_Array__get_Length
"Empty", // System_Array__Empty
"Copy", // System_Array__Copy
"ToBoolean", // System_Convert__ToBooleanDecimal
"ToBoolean", // System_Convert__ToBooleanInt32
"ToBoolean", // System_Convert__ToBooleanUInt32
......@@ -3641,6 +3682,10 @@ static WellKnownMembers()
".ctor", // Microsoft_CodeAnalysis_EmbeddedAttribute__ctor
".ctor", // System_Index__ctor
"FromEnd", // System_Index__FromEnd
"Value", // System_Index__Value
"Start", // System_Range__Start
"End", // System_Range__End
"Create", // System_Range__Create
"ToEnd", // System_Range__ToEnd
"FromStart", // System_Range__FromStart
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册