Example #1
0
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundSpillSequenceBuilder builder = null;
            var expression = VisitExpression(ref builder, node.Expression);

            BoundSpillSequenceBuilder indicesBuilder = null;
            var indices = this.VisitExpressionList(ref indicesBuilder, node.Indices);

            if (indicesBuilder != null)
            {
                // spill the array if there were await expressions in the indices
                if (builder == null)
                {
                    builder = new BoundSpillSequenceBuilder();
                }

                expression = Spill(builder, expression);
            }

            if (builder != null)
            {
                builder.Include(indicesBuilder);
                indicesBuilder = builder;
                builder        = null;
            }

            return(UpdateExpression(indicesBuilder, node.Update(expression, indices, node.Type)));
        }
Example #2
0
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundSpillSequence2 ssArray = null;
            var expression = VisitExpression(ref ssArray, node.Expression);

            BoundSpillSequence2 ssIndices = null;
            var indices = this.VisitExpressionList(ref ssIndices, node.Indices);

            if (ssIndices != null)
            {
                // spill the array if there were await expressions in the indices
                if (ssArray == null)
                {
                    ssArray = new BoundSpillSequence2();
                }
                expression = Spill(ssArray, expression);
            }

            if (ssArray != null)
            {
                ssArray.IncludeSequence(ssIndices);
                ssIndices = ssArray;
                ssArray   = null;
            }
            return(UpdateExpression(ssIndices, node.Update(expression, indices, node.Type)));
        }
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            if (_inExpressionLambda &&
                node.Indices.Length == 1 &&
                node.Indices[0].Type !.SpecialType == SpecialType.None)
            {
                Error(ErrorCode.ERR_ExpressionTreeContainsPatternIndexOrRangeIndexer, node);
            }

            return(base.VisitArrayAccess(node));
        }
        private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, FileLinePositionSpan span, SyntheticBoundNodeFactory statementFactory)
        {
            // Add an entry in the spans array.
            int spansIndex = _spansBuilder.Count;

            _spansBuilder.Add(new SourceSpan(GetSourceDocument(syntaxForSpan, span), span.StartLinePosition.Line, span.StartLinePosition.Character, span.EndLinePosition.Line, span.EndLinePosition.Character));

            // Generate "_payload[pointIndex] = true".
            BoundArrayAccess payloadCell = statementFactory.ArrayAccess(statementFactory.Local(_methodPayload), statementFactory.Literal(spansIndex));

            return(statementFactory.Assignment(payloadCell, statementFactory.Literal(true)));
        }
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundExpression expression = (BoundExpression)this.Visit(node.Expression);
            ReadOnlyArray <BoundExpression> indices = (ReadOnlyArray <BoundExpression>) this.VisitList(node.Indices);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence)
            {
                return(node.Update(expression, indices, type));
            }

            var             spillBuilder        = new SpillBuilder();
            var             spillResult         = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray <RefKind> .Empty);
            BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type);

            return(spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess));
        }
        private BoundExpression VisitArrayAccess(BoundArrayAccess node)
        {
            var array = Visit(node.Expression);

            if (node.Indices.Length == 1)
            {
                var arg   = node.Indices[0];
                var index = Visit(arg);
                if (index.Type != _int32Type)
                {
                    index = ConvertIndex(index, arg.Type, _int32Type);
                }
                return(ExprFactory("ArrayIndex", array, index));
            }
            else
            {
                return(ExprFactory("ArrayIndex", array, Indices(node.Indices)));
            }
        }
        private BoundExpression VisitArrayAccess(BoundArrayAccess node)
        {
            var array = Visit(node.Expression);

            if (node.Indices.Length == 1)
            {
                var arg   = node.Indices[0];
                var index = Visit(arg);
                if (!TypeSymbol.Equals(index.Type, _int32Type, TypeCompareKind.ConsiderEverything2))
                {
                    index = ConvertIndex(index, arg.Type, _int32Type);
                }
                return(ExprFactory("ArrayIndex", array, index));
            }
            else
            {
                return(ExprFactory("ArrayIndex", array, Indices(node.Indices)));
            }
        }
 private BoundExpression VisitArrayAccess(BoundArrayAccess node)
 {
     var array = Visit(node.Expression);
     if (node.Indices.Length == 1)
     {
         var arg = node.Indices[0];
         var index = Visit(arg);
         if (node.Type != _int32Type)
         {
             index = ConvertIndex(index, arg.Type, _int32Type);
         }
         return ExprFactory("ArrayIndex", array, index);
     }
     else
     {
         return ExprFactory("ArrayIndex", array, Indices(node.Indices));
     }
 }
Example #9
0
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundSpillSequence2 ssArray = null;
            var expression = VisitExpression(ref ssArray, node.Expression);

            BoundSpillSequence2 ssIndices = null;
            var indices = this.VisitExpressionList(ref ssIndices, node.Indices);

            if (ssIndices != null)
            {
                // spill the array if there were await expressions in the indices
                if (ssArray == null) ssArray = new BoundSpillSequence2();
                expression = Spill(ssArray, expression);
            }

            if (ssArray != null)
            {
                ssArray.IncludeSequence(ssIndices);
                ssIndices = ssArray;
                ssArray = null;
            }
            return UpdateExpression(ssIndices, node.Update(expression, indices, node.Type));
        }
Example #10
0
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            // https://github.com/dotnet/roslyn/issues/30620
            // If the array access index is of type System.Index or System.Range
            // we need to emit code as if there were a real indexer, instead
            // of a simple array element access.

            if (node.Indices.Length != 1)
            {
                return(base.VisitArrayAccess(node));
            }

            TypeSymbol rawIndexType = node.Indices[0].Type;

            if (!(TypeSymbol.Equals(rawIndexType, _compilation.GetWellKnownType(WellKnownType.System_Index), TypeCompareKind.ConsiderEverything) ||
                  TypeSymbol.Equals(rawIndexType, _compilation.GetWellKnownType(WellKnownType.System_Range), TypeCompareKind.ConsiderEverything)))
            {
                return(base.VisitArrayAccess(node));
            }

            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);

            var indexValueSymbol   = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Index__Value);
            var indexFromEndSymbol = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Index__IsFromEnd);

            BoundExpression resultExpr;

            if (TypeSymbol.Equals(indexType, _compilation.GetWellKnownType(WellKnownType.System_Index), TypeCompareKind.ConsiderEverything))
            {
                // array[Index] is translated to:
                // array[index.FromEnd ? array.Length - index.Value : index.Value]

                var indexValueExpr = F.Property(indexLocal, indexValueSymbol);

                resultExpr = F.Sequence(
                    ImmutableArray.Create <LocalSymbol>(
                        indexLocal.LocalSymbol,
                        arrayLocal.LocalSymbol),
                    ImmutableArray.Create <BoundExpression>(
                        indexAssign,
                        arrayAssign),
                    F.ArrayAccess(arrayLocal, ImmutableArray.Create(
                                      F.Conditional(
                                          F.Property(indexLocal, indexFromEndSymbol),
                                          F.Binary(
                                              BinaryOperatorKind.Subtraction,
                                              F.SpecialType(SpecialType.System_Int32),
                                              F.ArrayLength(arrayLocal),
                                              indexValueExpr),
                                          indexValueExpr,
                                          node.Type))));
            }
            else if (TypeSymbol.Equals(indexType, _compilation.GetWellKnownType(WellKnownType.System_Range), TypeCompareKind.ConsiderEverything))
            {
                // 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

                var rangeStartSymbol = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Range__Start);
                var rangeEndSymbol   = (PropertySymbol)F.WellKnownMember(WellKnownMember.System_Range__End);
                var arrayCopySymbol  = F.WellKnownMethod(WellKnownMember.System_Array__Copy);

                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, rangeStartSymbol), 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);
        }
Example #11
0
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            // An array access expression can be indexed using any of the following types:
            //   * an integer primitive
            //   * a System.Index
            //   * a System.Range
            // The last two are only supported on SZArrays. For those cases we need to
            // lower into the appropriate helper methods.

            if (node.Indices.Length != 1)
            {
                return(base.VisitArrayAccess(node));
            }

            var indexType = VisitType(node.Indices[0].Type);
            var F         = _factory;

            BoundNode resultExpr;

            if (TypeSymbol.Equals(
                    indexType,
                    _compilation.GetWellKnownType(WellKnownType.System_Index),
                    TypeCompareKind.ConsiderEverything))
            {
                // array[Index] is compiled to:
                // array[Index.GetOffset(array.Length)]

                var arrayLocal = F.StoreToTemp(
                    VisitExpression(node.Expression),
                    out BoundAssignmentOperator arrayAssign);

                resultExpr = F.Sequence(
                    ImmutableArray.Create(arrayLocal.LocalSymbol),
                    ImmutableArray.Create <BoundExpression>(arrayAssign),
                    F.ArrayAccess(
                        arrayLocal,
                        ImmutableArray.Create <BoundExpression>(
                            F.Call(
                                VisitExpression(node.Indices[0]),
                                WellKnownMember.System_Index__GetOffset,
                                F.ArrayLength(arrayLocal)))));
            }
            else if (TypeSymbol.Equals(
                         indexType,
                         _compilation.GetWellKnownType(WellKnownType.System_Range),
                         TypeCompareKind.ConsiderEverything))
            {
                // array[Range] is compiled to:
                // System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(array, Range)

                var elementType = ((ArrayTypeSymbol)node.Expression.Type).ElementTypeWithAnnotations;

                resultExpr = F.Call(
                    receiver: null,
                    F.WellKnownMethod(WellKnownMember.System_Runtime_CompilerServices_RuntimeHelpers__GetSubArray_T)
                    .Construct(ImmutableArray.Create(elementType)),
                    ImmutableArray.Create(
                        VisitExpression(node.Expression),
                        VisitExpression(node.Indices[0])));
            }
            else
            {
                resultExpr = base.VisitArrayAccess(node);
            }
            return(resultExpr);
        }
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundExpression expression = (BoundExpression)this.Visit(node.Expression);
            ReadOnlyArray<BoundExpression> indices = (ReadOnlyArray<BoundExpression>)this.VisitList(node.Indices);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence)
            {
                return node.Update(expression, indices, type);
            }

            var spillBuilder = new SpillBuilder();
            var spillResult = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray<RefKind>.Empty);
            BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type);
            return spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess);
        }