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

            return(UpdateExpression(builder, node.Update(expression, node.Type)));
        }
 //array length produces native uint, so the node typically implies a conversion to int32/int64.  
 //Sometimes the conversion is not necessary - i.e. when we just check for 0
 //This helper removes unnecessary implied conversion from ArrayLength node.
 private BoundExpression UnconvertArrayLength(BoundArrayLength arrLength)
 {
     return arrLength.Update(arrLength.Expression, _factory.SpecialType(SpecialType.System_UIntPtr));
 }
 private BoundExpression VisitArrayLength(BoundArrayLength node)
 {
     return ExprFactory("ArrayLength", Visit(node.Expression));
 }
Example #4
0
        private void EmitArrayLength(BoundArrayLength expression, bool used)
        {
            // The binder recognizes Array.Length and Array.LongLength and creates BoundArrayLength for them.
            // 
            // ArrayLength can be either 
            //      int32 for Array.Length
            //      int64 for Array.LongLength
            //      UIntPtr for synthetic code that needs just check if length != 0 - 
            //                  this is used in "fixed(int* ptr = arr)"
            Debug.Assert(expression.Type.SpecialType == SpecialType.System_Int32 ||
                expression.Type.SpecialType == SpecialType.System_Int64 ||
                expression.Type.SpecialType == SpecialType.System_UIntPtr);

            // ldlen will null-check the expression so it must be "used"
            EmitExpression(expression.Expression, used: true);
            _builder.EmitOpCode(ILOpCode.Ldlen);

            var typeTo = expression.Type.PrimitiveTypeCode;

            // NOTE: ldlen returns native uint, but newarr takes native int, so the length value is always 
            //       a positive native int. We can treat it as either signed or unsigned.
            //       We will use whatever typeTo says so we do not need to convert because of sign.
            var typeFrom = typeTo.IsUnsigned() ? Microsoft.Cci.PrimitiveTypeCode.UIntPtr : Microsoft.Cci.PrimitiveTypeCode.IntPtr;

            // NOTE: In Dev10 C# this cast is unchecked.
            // That seems to be wrong since that would cause silent truncation on 64bit platform if that implements large arrays. 
            // 
            // Emitting checked conversion however results in redundant overflow checks on 64bit and also inhibits range check hoisting in loops.
            // Therefore we will emit unchecked conversion here as C# compiler always did.
            _builder.EmitNumericConversion(typeFrom, typeTo, @checked: false);

            EmitPopIfUnused(used);
        }
Example #5
0
 public override BoundNode VisitArrayLength(BoundArrayLength node)
 {
     BoundSpillSequence2 ss = null;
     var expression = VisitExpression(ref ss, node.Expression);
     return UpdateExpression(ss, node.Update(expression, node.Type));
 }
 private BoundExpression VisitArrayLength(BoundArrayLength node)
 {
     return(ExprFactory("ArrayLength", Visit(node.Expression)));
 }
        /// <summary>
        /// Lower a foreach loop that will enumerate a single-dimensional array.
        ///
        /// A[] a = x;
        /// for (int p = 0; p &lt; a.Length; p = p + 1) {
        ///     V v = (V)a[p];
        ///     // body
        /// }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's
        /// implementation of IEnumerable and just indexing into its elements.
        ///
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);

            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            Debug.Assert(arrayType.IsSZArray);

            TypeSymbol intType  = _compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement  rewrittenBody       = (BoundStatement)Visit(node.Body);

            // A[] a
            LocalSymbol arrayVar = _factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray);

            // A[] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // Reference to a.
            BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // int p
            LocalSymbol positionVar = _factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayIndex);

            // Reference to p.
            BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType);

            // int p = 0;
            BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar,
                                                                  MakeLiteral(forEachSyntax, ConstantValue.Default(SpecialType.System_Int32), intType));

            // V v
            LocalSymbol iterationVar     = node.IterationVariable;
            TypeSymbol  iterationVarType = iterationVar.Type;

            // (V)a[p]
            BoundExpression iterationVarInitValue = MakeConversion(
                syntax: forEachSyntax,
                rewrittenOperand: new BoundArrayAccess(
                    syntax: forEachSyntax,
                    expression: boundArrayVar,
                    indices: ImmutableArray.Create <BoundExpression>(boundPositionVar),
                    type: arrayType.ElementType),
                conversion: node.ElementConversion,
                rewrittenType: iterationVarType,
                @checked: node.Checked);

            // V v = (V)a[p];
            BoundStatement iterationVariableDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVariableDecl);

            BoundStatement initializer = new BoundStatementList(forEachSyntax,
                                                                statements: ImmutableArray.Create <BoundStatement>(arrayVarDecl, positionVarDecl));

            // a.Length
            BoundExpression arrayLength = new BoundArrayLength(
                syntax: forEachSyntax,
                expression: boundArrayVar,
                type: intType);

            // p < a.Length
            BoundExpression exitCondition = new BoundBinaryOperator(
                syntax: forEachSyntax,
                operatorKind: BinaryOperatorKind.IntLessThan,
                left: boundPositionVar,
                right: arrayLength,
                constantValueOpt: null,
                methodOpt: null,
                resultKind: LookupResultKind.Viable,
                type: boolType);

            // p = p + 1;
            BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType);

            // { V v = (V)a[p]; /* node.Body */ }

            BoundStatement loopBody = CreateBlockDeclaringIterationVariable(iterationVar, iterationVariableDecl, rewrittenBody, forEachSyntax);

            // for (A[] a = /*node.Expression*/, int p = 0; p < a.Length; p = p + 1) {
            //     V v = (V)a[p];
            //     /*node.Body*/
            // }
            BoundStatement result = RewriteForStatement(
                syntax: node.Syntax,
                outerLocals: ImmutableArray.Create <LocalSymbol>(arrayVar, positionVar),
                rewrittenInitializer: initializer,
                rewrittenCondition: exitCondition,
                conditionSyntaxOpt: null,
                conditionSpanOpt: forEachSyntax.InKeyword.Span,
                rewrittenIncrement: positionIncrement,
                rewrittenBody: loopBody,
                breakLabel: node.BreakLabel,
                continueLabel: node.ContinueLabel,
                hasErrors: node.HasErrors);

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return(result);
        }
        /// <summary>
        /// Lower a foreach loop that will enumerate a single-dimensional array.
        /// 
        /// A[] a = x;
        /// for (int p = 0; p &lt; a.Length; p = p + 1) {
        ///     V v = (V)a[p];
        ///     // body
        /// }
        /// </summary>
        /// <remarks>
        /// We will follow Dev10 in diverging from the C# 4 spec by ignoring Array's 
        /// implementation of IEnumerable and just indexing into its elements.
        /// 
        /// NOTE: We're assuming that sequence points have already been generated.
        /// Otherwise, lowering to for-loops would generated spurious ones.
        /// </remarks>
        private BoundStatement RewriteSingleDimensionalArrayForEachStatement(BoundForEachStatement node)
        {
            ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)node.Syntax;

            BoundExpression collectionExpression = GetUnconvertedCollectionExpression(node);
            Debug.Assert(collectionExpression.Type.IsArray());

            ArrayTypeSymbol arrayType = (ArrayTypeSymbol)collectionExpression.Type;

            Debug.Assert(arrayType.IsSZArray);

            TypeSymbol intType = _compilation.GetSpecialType(SpecialType.System_Int32);
            TypeSymbol boolType = _compilation.GetSpecialType(SpecialType.System_Boolean);

            BoundExpression rewrittenExpression = (BoundExpression)Visit(collectionExpression);
            BoundStatement rewrittenBody = (BoundStatement)Visit(node.Body);

            // A[] a
            LocalSymbol arrayVar = _factory.SynthesizedLocal(arrayType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArray);

            // A[] a = /*node.Expression*/;
            BoundStatement arrayVarDecl = MakeLocalDeclaration(forEachSyntax, arrayVar, rewrittenExpression);

            AddForEachExpressionSequencePoint(forEachSyntax, ref arrayVarDecl);

            // Reference to a.
            BoundLocal boundArrayVar = MakeBoundLocal(forEachSyntax, arrayVar, arrayType);

            // int p
            LocalSymbol positionVar = _factory.SynthesizedLocal(intType, syntax: forEachSyntax, kind: SynthesizedLocalKind.ForEachArrayIndex);

            // Reference to p.
            BoundLocal boundPositionVar = MakeBoundLocal(forEachSyntax, positionVar, intType);

            // int p = 0;
            BoundStatement positionVarDecl = MakeLocalDeclaration(forEachSyntax, positionVar,
                MakeLiteral(forEachSyntax, ConstantValue.Default(SpecialType.System_Int32), intType));

            // V v
            LocalSymbol iterationVar = node.IterationVariable;
            TypeSymbol iterationVarType = iterationVar.Type;

            // (V)a[p]
            BoundExpression iterationVarInitValue = MakeConversion(
                syntax: forEachSyntax,
                rewrittenOperand: new BoundArrayAccess(
                    syntax: forEachSyntax,
                    expression: boundArrayVar,
                    indices: ImmutableArray.Create<BoundExpression>(boundPositionVar),
                    type: arrayType.ElementType),
                conversion: node.ElementConversion,
                rewrittenType: iterationVarType,
                @checked: node.Checked);

            // V v = (V)a[p];
            BoundStatement iterationVariableDecl = MakeLocalDeclaration(forEachSyntax, iterationVar, iterationVarInitValue);

            AddForEachIterationVariableSequencePoint(forEachSyntax, ref iterationVariableDecl);

            BoundStatement initializer = new BoundStatementList(forEachSyntax,
                        statements: ImmutableArray.Create<BoundStatement>(arrayVarDecl, positionVarDecl));

            // a.Length
            BoundExpression arrayLength = new BoundArrayLength(
                syntax: forEachSyntax,
                expression: boundArrayVar,
                type: intType);

            // p < a.Length
            BoundExpression exitCondition = new BoundBinaryOperator(
                syntax: forEachSyntax,
                operatorKind: BinaryOperatorKind.IntLessThan,
                left: boundPositionVar,
                right: arrayLength,
                constantValueOpt: null,
                methodOpt: null,
                resultKind: LookupResultKind.Viable,
                type: boolType);

            // p = p + 1;
            BoundStatement positionIncrement = MakePositionIncrement(forEachSyntax, boundPositionVar, intType);

            // { V v = (V)a[p]; /* node.Body */ }

            BoundStatement loopBody = CreateBlockDeclaringIterationVariable(iterationVar, iterationVariableDecl, rewrittenBody, forEachSyntax);

            // for (A[] a = /*node.Expression*/, int p = 0; p < a.Length; p = p + 1) {
            //     V v = (V)a[p];
            //     /*node.Body*/
            // }
            BoundStatement result = RewriteForStatement(
                syntax: node.Syntax,
                outerLocals: ImmutableArray.Create<LocalSymbol>(arrayVar, positionVar),
                rewrittenInitializer: initializer,
                rewrittenCondition: exitCondition,
                conditionSyntaxOpt: null,
                conditionSpanOpt: forEachSyntax.InKeyword.Span,
                rewrittenIncrement: positionIncrement,
                rewrittenBody: loopBody,
                breakLabel: node.BreakLabel,
                continueLabel: node.ContinueLabel,
                hasErrors: node.HasErrors);

            AddForEachKeywordSequencePoint(forEachSyntax, ref result);

            return result;
        }
Example #9
0
 internal void Parse(BoundArrayLength boundArrayLength)
 {
     base.Parse(boundArrayLength);
     this.Expression1 = Deserialize(boundArrayLength.Expression) as Expression;
 }