Ejemplo n.º 1
0
        private BoundNode RewriteCatch(BoundCatchBlock node, ArrayBuilder <BoundExpression> prologue, ArrayBuilder <LocalSymbol> newLocals)
        {
            AddLocals(node.Locals, newLocals);
            var rewrittenCatchLocals = newLocals.ToImmutableAndFree();

            // If exception variable got lifted, IntroduceFrame will give us frame init prologue.
            // It needs to run before the exception variable is accessed.
            // To ensure that, we will make exception variable a sequence that performs prologue as its its sideeffecs.
            BoundExpression rewrittenExceptionSource = null;
            var             rewrittenFilter          = (BoundExpression)this.Visit(node.ExceptionFilterOpt);

            if (node.ExceptionSourceOpt != null)
            {
                rewrittenExceptionSource = (BoundExpression)Visit(node.ExceptionSourceOpt);
                if (prologue.Count > 0)
                {
                    rewrittenExceptionSource = new BoundSequence(
                        rewrittenExceptionSource.Syntax,
                        ImmutableArray.Create <LocalSymbol>(),
                        prologue.ToImmutable(),
                        rewrittenExceptionSource,
                        rewrittenExceptionSource.Type);
                }
            }
            else if (prologue.Count > 0)
            {
                Debug.Assert(rewrittenFilter != null);
                rewrittenFilter = new BoundSequence(
                    rewrittenFilter.Syntax,
                    ImmutableArray.Create <LocalSymbol>(),
                    prologue.ToImmutable(),
                    rewrittenFilter,
                    rewrittenFilter.Type);
            }

            // done with this.
            prologue.Free();

            // rewrite filter and body
            // NOTE: this will proxy all accesses to exception local if that got lifted.
            var exceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);
            var rewrittenBlock   = (BoundBlock)this.Visit(node.Body);

            return(node.Update(
                       rewrittenCatchLocals,
                       rewrittenExceptionSource,
                       exceptionTypeOpt,
                       rewrittenFilter,
                       rewrittenBlock));
        }
Ejemplo n.º 2
0
        override protected ImmutableArray <LocalSymbol> BuildLocals()
        {
            if (_syntax.Declaration != null)
            {
                var locals = new ArrayBuilder <LocalSymbol>(_syntax.Declaration.Variables.Count);

                _syntax.Declaration.Type.VisitRankSpecifiers((rankSpecifier, args) =>
                {
                    foreach (var size in rankSpecifier.Sizes)
                    {
                        if (size.Kind() != SyntaxKind.OmittedArraySizeExpression)
                        {
                            ExpressionVariableFinder.FindExpressionVariables(args.binder, args.locals, size);
                        }
                    }
                }, (binder: this, locals: locals));

                foreach (VariableDeclaratorSyntax declarator in _syntax.Declaration.Variables)
                {
                    locals.Add(MakeLocal(_syntax.Declaration, declarator, LocalDeclarationKind.FixedVariable));

                    // also gather expression-declared variables from the bracketed argument lists and the initializers
                    ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator);
                }

                return(locals.ToImmutable());
            }

            return(ImmutableArray <LocalSymbol> .Empty);
        }
Ejemplo n.º 3
0
        internal static SourceText ToSourceText(
            ArrayBuilder <SourceText> segments,
            SourceText original,
            bool adjustSegments
            )
        {
            if (adjustSegments)
            {
                TrimInaccessibleText(segments);
                ReduceSegmentCountIfNecessary(segments);
            }

            if (segments.Count == 0)
            {
                return(SourceText.From(string.Empty, original.Encoding, original.ChecksumAlgorithm));
            }
            else if (segments.Count == 1)
            {
                return(segments[0]);
            }
            else
            {
                return(new CompositeText(
                           segments.ToImmutable(),
                           original.Encoding,
                           original.ChecksumAlgorithm
                           ));
            }
        }
Ejemplo n.º 4
0
 public CacheEntry ToReferenceCacheEntry()
 {
     return(new CacheEntry(
                _checksum,
                _language,
                _itemsBuilder.ToImmutable()));
 }
Ejemplo n.º 5
0
        public DataModel()
        {
            var fields = from field in typeof(FunctionId).GetFields()
                         where !field.IsSpecialName
                         select field;

            var builder = new ArrayBuilder <ActivityLevel?>();

            var features = new Dictionary <string, ActivityLevel>();
            var root     = new ActivityLevel("All");

            foreach (var field in fields)
            {
                var value        = (int)field.GetRawConstantValue();
                var name         = field.Name;
                var featureNames = name.Split('_');
                var featureName  = featureNames.Length > 1 ? featureNames[0] : "Uncategorized";

                if (!features.TryGetValue(featureName, out var parent))
                {
                    parent = new ActivityLevel(featureName, root, createChildList: true);
                    features[featureName] = parent;
                }

                builder.SetItem(value, new ActivityLevel(name, parent, createChildList: false));
            }

            _activities = builder.ToImmutable();
            root.SortChildren();
            RootNode = root;
        }
 public CacheEntry ToCacheEntry()
 {
     return(new CacheEntry(
                _checksum,
                _language,
                _simpleItemBuilder,
                _complexItemBuilder.ToImmutable()));
 }
Ejemplo n.º 7
0
            public ImmutableArray <BoundStatement> GetStatements()
            {
                if (_statements == null)
                {
                    return(ImmutableArray <BoundStatement> .Empty);
                }

                return(_statements.ToImmutable());
            }
 public TypeImportCompletionCacheEntry ToReferenceCacheEntry()
 {
     return(new TypeImportCompletionCacheEntry(
                _assemblySymbolKey,
                _checksum,
                _language,
                _itemsBuilder.ToImmutable(),
                _publicItemCount));
 }
Ejemplo n.º 9
0
            private void AddConjunct(BoundExpression test)
            {
                if (_sideEffectBuilder.Count != 0)
                {
                    test = _factory.Sequence(ImmutableArray <LocalSymbol> .Empty, _sideEffectBuilder.ToImmutable(), test);
                    _sideEffectBuilder.Clear();
                }

                _conjunctBuilder.Add(test);
            }
Ejemplo n.º 10
0
 private static ImmutableArray <RefKind> GetRefKindsOrNull(ArrayBuilder <RefKind> refKinds)
 {
     foreach (var refKind in refKinds)
     {
         if (refKind != RefKind.None)
         {
             return(refKinds.ToImmutable());
         }
     }
     return(default(ImmutableArray <RefKind>));
 }
Ejemplo n.º 11
0
 public static PropertySetAbstractValue GetInstance(ArrayBuilder <PropertySetAbstractValueKind> propertyAbstractValues)
 {
     if (TryGetPooledInstance(propertyAbstractValues, out PropertySetAbstractValue instance))
     {
         return(instance);
     }
     else
     {
         return(new PropertySetAbstractValue(propertyAbstractValues.ToImmutable()));
     }
 }
Ejemplo n.º 12
0
 public ImmutableArray <Cci.ILocalDefinition> LocalsInOrder()
 {
     if (_lazyAllLocals == null)
     {
         return(ImmutableArray <Cci.ILocalDefinition> .Empty);
     }
     else
     {
         return(_lazyAllLocals.ToImmutable());
     }
 }
Ejemplo n.º 13
0
            public ImmutableArray <BoundStatement> GetStatements(LocalSubstituter substituterOpt = null)
            {
                if (_statements == null)
                {
                    return(ImmutableArray <BoundStatement> .Empty);
                }

                if (substituterOpt == null)
                {
                    return(_statements.ToImmutable());
                }

                return(_statements.SelectAsArray((statement, substituter) => (BoundStatement)substituter.Visit(statement), substituterOpt));
            }
        override protected ImmutableArray<LocalSymbol> BuildLocals()
        {
            if (_syntax.Declaration != null)
            {
                var locals = new ArrayBuilder<LocalSymbol>(_syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in _syntax.Declaration.Variables)
                {
                    locals.Add(MakeLocal(_syntax.Declaration, declarator, LocalDeclarationKind.FixedVariable));
                }

                return locals.ToImmutable();
            }

            return ImmutableArray<LocalSymbol>.Empty;
        }
Ejemplo n.º 15
0
        override protected ImmutableArray <LocalSymbol> BuildLocals()
        {
            if (syntax.Declaration != null)
            {
                var locals = new ArrayBuilder <LocalSymbol>(syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in syntax.Declaration.Variables)
                {
                    locals.Add(SourceLocalSymbol.MakeLocal(this.Owner, this, syntax.Declaration.Type, declarator.Identifier, declarator.Initializer, LocalDeclarationKind.Using));
                }

                return(locals.ToImmutable());
            }

            return(ImmutableArray <LocalSymbol> .Empty);
        }
Ejemplo n.º 16
0
        override protected ImmutableArray <LocalSymbol> BuildLocals()
        {
            if (_syntax.Declaration != null)
            {
                var locals = new ArrayBuilder <LocalSymbol>(1);
                locals.Add(MakeLocal(_syntax.Declaration, LocalDeclarationKind.FixedVariable));

                // also gather expression-declared variables from the bracketed argument lists and the initializers
                ExpressionVariableFinder.FindExpressionVariables(this, locals, _syntax.Declaration);

                return(locals.ToImmutable());
            }

            return(ImmutableArray <LocalSymbol> .Empty);
        }
Ejemplo n.º 17
0
        private ImmutableArray <StatementSyntax> Analyze()
        {
            bool badRegion = false;

            // only one pass is needed.
            Scan(ref badRegion);

            if (badRegion)
            {
                return(ImmutableArray <StatementSyntax> .Empty);
            }

            _branchesOutOf.Sort((x, y) => x.SpanStart - y.SpanStart);
            return(_branchesOutOf.ToImmutable());
        }
Ejemplo n.º 18
0
        override protected ImmutableArray <LocalSymbol> BuildLocals()
        {
            if (syntax.Declaration != null)
            {
                var locals = new ArrayBuilder <LocalSymbol>(syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in syntax.Declaration.Variables)
                {
                    locals.Add(MakeLocal(syntax.Declaration, declarator, LocalDeclarationKind.UsingVariable));
                }

                return(locals.ToImmutable());
            }

            return(ImmutableArray <LocalSymbol> .Empty);
        }
Ejemplo n.º 19
0
        override protected ImmutableArray<LocalSymbol> BuildLocals()
        {
            if (syntax.Declaration != null)
            {
                var locals = new ArrayBuilder<LocalSymbol>(syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in syntax.Declaration.Variables)
                {
                    locals.Add(SourceLocalSymbol.MakeLocal(this.Owner, this, syntax.Declaration.Type, declarator.Identifier, declarator.Initializer, LocalDeclarationKind.Fixed));
                }

                return locals.ToImmutable();
            }

            return ImmutableArray<LocalSymbol>.Empty;
        }
Ejemplo n.º 20
0
        internal ImmutableArray <Symbol> BindXmlNameAttribute(
            XmlNameAttributeSyntax syntax,
            ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
            )
        {
            var identifier = syntax.Identifier;

            if (identifier.IsMissing)
            {
                return(ImmutableArray <Symbol> .Empty);
            }

            var name = identifier.Identifier.ValueText;

            var lookupResult = LookupResult.GetInstance();

            this.LookupSymbolsWithFallback(
                lookupResult,
                name,
                arity: 0,
                useSiteInfo: ref useSiteInfo
                );

            if (lookupResult.Kind == LookupResultKind.Empty)
            {
                lookupResult.Free();
                return(ImmutableArray <Symbol> .Empty);
            }

            // If we found something, it must be viable, since only parameters or type parameters
            // of the current member are considered.
            Debug.Assert(lookupResult.IsMultiViable);

            ArrayBuilder <Symbol> lookupSymbols = lookupResult.Symbols;

            Debug.Assert(
                lookupSymbols[0].Kind == SymbolKind.TypeParameter ||
                lookupSymbols[0].Kind == SymbolKind.Parameter
                );
            Debug.Assert(lookupSymbols.All(sym => sym.Kind == lookupSymbols[0].Kind));

            // We can sort later when we disambiguate.
            ImmutableArray <Symbol> result = lookupSymbols.ToImmutable();

            lookupResult.Free();

            return(result);
        }
Ejemplo n.º 21
0
        override protected ImmutableArray<LocalSymbol> BuildLocals()
        {
            if (_syntax.Declaration != null)
            {
                var locals = new ArrayBuilder<LocalSymbol>(_syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in _syntax.Declaration.Variables)
                {
                    locals.Add(MakeLocal(_syntax.Declaration, declarator, LocalDeclarationKind.FixedVariable));

                    // also gather expression-declared variables from the bracketed argument lists and the initializers
                    ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator);
                }

                return locals.ToImmutable();
            }

            return ImmutableArray<LocalSymbol>.Empty;
        }
Ejemplo n.º 22
0
        override protected ImmutableArray<LocalSymbol> BuildLocals()
        {
            if (_syntax.Declaration != null)
            {
                var locals = new ArrayBuilder<LocalSymbol>(_syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in _syntax.Declaration.Variables)
                {
                    locals.Add(MakeLocal(_syntax.Declaration, declarator, LocalDeclarationKind.FixedVariable));

                    if (declarator.Initializer != null)
                    {
                        ExpressionVariableFinder.FindExpressionVariables(this, locals, declarator.Initializer.Value);
                    }
                }

                return locals.ToImmutable();
            }

            return ImmutableArray<LocalSymbol>.Empty;
        }
Ejemplo n.º 23
0
        override protected ImmutableArray <LocalSymbol> BuildLocals()
        {
            if (_syntax.Declaration != null)
            {
                var locals = new ArrayBuilder <LocalSymbol>(_syntax.Declaration.Variables.Count);
                foreach (VariableDeclaratorSyntax declarator in _syntax.Declaration.Variables)
                {
                    locals.Add(MakeLocal(RefKind.None, _syntax.Declaration, declarator, LocalDeclarationKind.FixedVariable));

                    if (declarator.Initializer != null)
                    {
                        PatternVariableFinder.FindPatternVariables(this, locals, declarator.Initializer.Value);
                    }
                }

                return(locals.ToImmutable());
            }

            return(ImmutableArray <LocalSymbol> .Empty);
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Get the import strings for a given method, following forward pointers as necessary.
        /// </summary>
        /// <returns>
        /// For each namespace enclosing the method, a list of import strings, innermost to outermost.
        /// There should always be at least one entry, for the global namespace.
        /// </returns>
        public static ImmutableArray <ImmutableArray <string> > GetCSharpGroupedImportStrings(this ISymUnmanagedReader reader, int methodToken, out ImmutableArray <string> externAliasStrings)
        {
            externAliasStrings = default(ImmutableArray <string>);

            ImmutableArray <short> groupSizes = default(ImmutableArray <short>);
            bool seenForward = false;

RETRY:
            var bytes = reader.GetCustomDebugInfo(methodToken);

            if (bytes == null)
            {
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            int offset = 0;

            byte globalVersion;
            byte unusedGlobalCount;

            ReadGlobalHeader(bytes, ref offset, out globalVersion, out unusedGlobalCount);
            CheckVersion(globalVersion, methodToken);

            while (offset < bytes.Length)
            {
                byte version;
                CustomDebugInfoKind kind;
                int size;
                ReadRecordHeader(bytes, ref offset, out version, out kind, out size);
                CheckVersion(version, methodToken);

                if (kind == CustomDebugInfoKind.UsingInfo)
                {
                    if (!groupSizes.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Expected at most one Using record for method {0}", FormatMethodToken(methodToken)));
                    }

                    ReadUsingRecord(bytes, ref offset, size, out groupSizes);
                }
                else if (kind == CustomDebugInfoKind.ForwardInfo)
                {
                    if (!externAliasStrings.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Did not expect both Forward and ForwardToModule records for method {0}", FormatMethodToken(methodToken)));
                    }

                    ReadForwardRecord(bytes, ref offset, size, out methodToken);
                    if (!seenForward) // Follow at most one forward link.
                    {
                        seenForward = true;
                        goto RETRY;
                    }
                }
                else if (kind == CustomDebugInfoKind.ForwardToModuleInfo)
                {
                    if (!externAliasStrings.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Expected at most one ForwardToModule record for method {0}", FormatMethodToken(methodToken)));
                    }

                    int moduleInfoMethodToken;
                    ReadForwardToModuleRecord(bytes, ref offset, size, out moduleInfoMethodToken);
                    ImmutableArray <string> allModuleInfoImportStrings = GetImportStrings(reader.GetBaselineMethod(moduleInfoMethodToken));
                    ArrayBuilder <string>   externAliasBuilder         = ArrayBuilder <string> .GetInstance();

                    foreach (string importString in allModuleInfoImportStrings)
                    {
                        if (IsCSharpExternAliasInfo(importString))
                        {
                            externAliasBuilder.Add(importString);
                        }
                    }
                    externAliasStrings = externAliasBuilder.ToImmutableAndFree();
                }
                else
                {
                    SkipRecord(bytes, ref offset, size);
                }
            }

            if (groupSizes.IsDefault)
            {
                throw new InvalidOperationException(string.Format("Didn't find usings info for method {0}", FormatMethodToken(methodToken)));
            }

            ImmutableArray <string> importStrings = GetImportStrings(reader.GetBaselineMethod(methodToken));
            int numImportStrings = importStrings.Length;

            ArrayBuilder <ImmutableArray <string> > resultBuilder = ArrayBuilder <ImmutableArray <string> > .GetInstance(groupSizes.Length);

            ArrayBuilder <string> groupBuilder = ArrayBuilder <string> .GetInstance();

            int pos = 0;

            foreach (short groupSize in groupSizes)
            {
                for (int i = 0; i < groupSize; i++, pos++)
                {
                    if (pos >= numImportStrings)
                    {
                        throw new InvalidOperationException(string.Format("Group size indicates more imports than there are import strings (method {0}).", FormatMethodToken(methodToken)));
                    }

                    string importString = importStrings[pos];
                    if (IsCSharpExternAliasInfo(importString))
                    {
                        throw new InvalidOperationException(string.Format("Encountered extern alias info before all import strings were consumed (method {0}).", FormatMethodToken(methodToken)));
                    }

                    groupBuilder.Add(importString);
                }

                resultBuilder.Add(groupBuilder.ToImmutable());
                groupBuilder.Clear();
            }


            if (externAliasStrings.IsDefault)
            {
                Debug.Assert(groupBuilder.Count == 0);

                // Extern alias detail strings (prefix "Z") are not included in the group counts.
                for (; pos < numImportStrings; pos++)
                {
                    string importString = importStrings[pos];
                    if (!IsCSharpExternAliasInfo(importString))
                    {
                        throw new InvalidOperationException(string.Format("Expected only extern alias info strings after consuming the indicated number of imports (method {0}).", FormatMethodToken(methodToken)));
                    }

                    groupBuilder.Add(importString);
                }

                externAliasStrings = groupBuilder.ToImmutableAndFree();
            }
            else
            {
                groupBuilder.Free();

                if (pos < numImportStrings)
                {
                    throw new InvalidOperationException(string.Format("Group size indicates fewer imports than there are import strings (method {0}).", FormatMethodToken(methodToken)));
                }
            }

            return(resultBuilder.ToImmutableAndFree());
        }
Ejemplo n.º 25
0
 public ImmutableArray <LocalSymbol> GetLocals()
 {
     return((_locals == null) ? ImmutableArray <LocalSymbol> .Empty : _locals.ToImmutable());
 }
Ejemplo n.º 26
0
        /// <summary>
        /// The strategy of this rewrite is to do rewrite "locally".
        /// We analyze arguments of the concat in a shallow fashion assuming that
        /// lowering and optimizations (including this one) is already done for the arguments.
        /// Based on the arguments we select the most appropriate pattern for the current node.
        ///
        /// NOTE: it is not guaranteed that the node that we chose will be the most optimal since we have only
        ///       local information - i.e. we look at the arguments, but we do not know about siblings.
        ///       When we move to the parent, the node may be rewritten by this or some another optimization.
        ///
        /// Example:
        ///     result = ( "abc" + "def" + null ?? expr1 + "moo" + "baz" ) + expr2
        ///
        /// Will rewrite into:
        ///     result = Concat("abcdef", expr2)
        ///
        /// However there will be transient nodes like  Concat(expr1 + "moo")  that will not be present in the
        /// resulting tree.
        ///
        /// </summary>
        private BoundExpression RewriteStringConcatenation(SyntaxNode syntax, BinaryOperatorKind operatorKind, BoundExpression loweredLeft, BoundExpression loweredRight, TypeSymbol type)
        {
            Debug.Assert(
                operatorKind == BinaryOperatorKind.StringConcatenation ||
                operatorKind == BinaryOperatorKind.StringAndObjectConcatenation ||
                operatorKind == BinaryOperatorKind.ObjectAndStringConcatenation);

            if (_inExpressionLambda)
            {
                return(RewriteStringConcatInExpressionLambda(syntax, operatorKind, loweredLeft, loweredRight, type));
            }

            // Convert both sides to a string (calling ToString if necessary)
            loweredLeft  = ConvertConcatExprToString(syntax, loweredLeft);
            loweredRight = ConvertConcatExprToString(syntax, loweredRight);

            Debug.Assert(loweredLeft.Type.IsStringType() || loweredLeft.ConstantValue?.IsNull == true || loweredLeft.Type.IsErrorType());
            Debug.Assert(loweredRight.Type.IsStringType() || loweredRight.ConstantValue?.IsNull == true || loweredRight.Type.IsErrorType());

            // try fold two args without flattening.
            var folded = TryFoldTwoConcatOperands(syntax, loweredLeft, loweredRight);

            if (folded != null)
            {
                return(folded);
            }

            // flatten and merge -  ( expr1 + "A" ) + ("B" + expr2) ===> (expr1 + "AB" + expr2)
            ArrayBuilder <BoundExpression> leftFlattened = ArrayBuilder <BoundExpression> .GetInstance();

            ArrayBuilder <BoundExpression> rightFlattened = ArrayBuilder <BoundExpression> .GetInstance();

            FlattenConcatArg(loweredLeft, leftFlattened);
            FlattenConcatArg(loweredRight, rightFlattened);

            if (leftFlattened.Any() && rightFlattened.Any())
            {
                folded = TryFoldTwoConcatOperands(syntax, leftFlattened.Last(), rightFlattened.First());
                if (folded != null)
                {
                    rightFlattened[0] = folded;
                    leftFlattened.RemoveLast();
                }
            }

            leftFlattened.AddRange(rightFlattened);
            rightFlattened.Free();

            BoundExpression result;

            switch (leftFlattened.Count)
            {
            case 0:
                result = _factory.StringLiteral(string.Empty);
                break;

            case 1:
                // All code paths which reach here (through TryFoldTwoConcatOperands) have already called
                // RewriteStringConcatenationOneExpr if necessary
                result = leftFlattened[0];
                break;

            case 2:
                var left  = leftFlattened[0];
                var right = leftFlattened[1];
                result = RewriteStringConcatenationTwoExprs(syntax, left, right);
                break;

            case 3:
            {
                var first  = leftFlattened[0];
                var second = leftFlattened[1];
                var third  = leftFlattened[2];
                result = RewriteStringConcatenationThreeExprs(syntax, first, second, third);
            }
            break;

            case 4:
            {
                var first  = leftFlattened[0];
                var second = leftFlattened[1];
                var third  = leftFlattened[2];
                var fourth = leftFlattened[3];
                result = RewriteStringConcatenationFourExprs(syntax, first, second, third, fourth);
            }
            break;

            default:
                result = RewriteStringConcatenationManyExprs(syntax, leftFlattened.ToImmutable());
                break;
            }

            leftFlattened.Free();
            return(result);
        }
Ejemplo n.º 27
0
        public void RetargetExtensionMethods()
        {
            var source =
                @"class C
{
}
static class S1
{
    internal static void E(this object x, object y) { }
}
static class S2
{
    internal static void E<T, U>(this T t, U u) { }
}";
            var compilation = CreateCompilation(source);

            var sourceModule    = compilation.SourceModule;
            var sourceAssembly  = (SourceAssemblySymbol)sourceModule.ContainingAssembly;
            var sourceNamespace = sourceModule.GlobalNamespace;

            var retargetingAssembly = new RetargetingAssemblySymbol(sourceAssembly, isLinked: false);

            retargetingAssembly.SetCorLibrary(sourceAssembly.CorLibrary);
            var retargetingModule    = retargetingAssembly.Modules[0];
            var retargetingNamespace = retargetingModule.GlobalNamespace;

            var sourceMethods = new ArrayBuilder <MethodSymbol>();

            sourceNamespace.GetExtensionMethods(sourceMethods, null, 0, LookupOptions.AllMethodsOnArityZero);
            Utils.CheckSymbols(sourceMethods.ToImmutable(),
                               "void S1.E(object x, object y)",
                               "void S2.E<T, U>(T t, U u)");

            var retargetingMethods = new ArrayBuilder <MethodSymbol>();

            retargetingNamespace.GetExtensionMethods(retargetingMethods, null, 0, LookupOptions.AllMethodsOnArityZero);
            Utils.CheckSymbols(retargetingMethods.ToImmutable(),
                               "void S1.E(object x, object y)",
                               "void S2.E<T, U>(T t, U u)");

            for (int i = 0; i < sourceMethods.Count; i++)
            {
                CheckMethods(sourceMethods[i], retargetingMethods[i]);
            }

            sourceMethods = new ArrayBuilder <MethodSymbol>();
            sourceNamespace.GetExtensionMethods(sourceMethods, "E", 2, LookupOptions.Default);
            Utils.CheckSymbols(sourceMethods.ToImmutable(),
                               "void S2.E<T, U>(T t, U u)");
            var sourceMethod = sourceMethods[0];

            retargetingMethods = new ArrayBuilder <MethodSymbol>();
            retargetingNamespace.GetExtensionMethods(retargetingMethods, "E", 2, LookupOptions.Default);
            Utils.CheckSymbols(retargetingMethods.ToImmutable(),
                               "void S2.E<T, U>(T t, U u)");
            var retargetingMethod = retargetingMethods[0];

            var sourceType      = sourceNamespace.GetMember <NamedTypeSymbol>("C");
            var retargetingType = retargetingNamespace.GetMember <NamedTypeSymbol>("C");

            CheckTypes(sourceType, retargetingType);

            CheckMethods(sourceMethod, retargetingMethod);
            var sourceReduced      = sourceMethod.ReduceExtensionMethod(sourceType);
            var retargetingReduced = retargetingMethod.ReduceExtensionMethod(retargetingType);

            CheckReducedExtensionMethods(sourceReduced, retargetingReduced);
        }
Ejemplo n.º 28
0
        private BoundNode RewriteCatch(BoundCatchBlock node, ArrayBuilder <BoundExpression> prologue, ArrayBuilder <LocalSymbol> newLocals)
        {
            LocalSymbol rewrittenCatchLocal = null;

            if (newLocals.Count > 0)
            {
                Debug.Assert(newLocals.Count == 1, "must be only one local that is the frame reference");
                Debug.Assert(this.proxies.ContainsKey(node.LocalOpt), "original local should be proxied");

                // getting new locals means that our original local was lifted into a closure
                // and instead of an actual local catch will own frame reference.
                rewrittenCatchLocal = newLocals[0];
            }
            else if (node.LocalOpt != null)
            {
                // local was not lifted, but its type may need to be rewritten
                // this happens when it has a generic type which needs to be rewritten
                // when lambda body was moved to a separate method.
                var origLocal = node.LocalOpt;
                Debug.Assert(!this.proxies.ContainsKey(origLocal), "captured local should not need rewriting");

                var newType = VisitType(origLocal.Type);
                if (newType == origLocal.Type)
                {
                    // keeping same local
                    rewrittenCatchLocal = origLocal;
                }
                else
                {
                    //  need a local of a different type
                    rewrittenCatchLocal = new SynthesizedLocal(CurrentMethod, newType, origLocal.Name, declarationKind: LocalDeclarationKind.Catch);
                    localMap.Add(origLocal, rewrittenCatchLocal);
                }
            }

            // If exception variable got lifted, IntroduceFrame will give us frame init prologue.
            // It needs to run before the exception variable is accessed.
            // To ensure that, we will make exception variable a sequence that performs prologue as its its sideeffecs.
            BoundExpression rewrittenExceptionSource = null;

            if (node.ExceptionSourceOpt != null)
            {
                rewrittenExceptionSource = (BoundExpression)Visit(node.ExceptionSourceOpt);
                if (prologue.Count > 0)
                {
                    rewrittenExceptionSource = new BoundSequence(
                        rewrittenExceptionSource.Syntax,
                        ImmutableArray.Create <LocalSymbol>(),
                        prologue.ToImmutable(),
                        rewrittenExceptionSource,
                        rewrittenExceptionSource.Type);
                }
            }

            // done with these.
            newLocals.Free();
            prologue.Free();

            // rewrite filter and body
            // NOTE: this will proxy all accesses to exception local if that got lifted.
            var exceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt);
            var rewrittenFilter  = (BoundExpression)this.Visit(node.ExceptionFilterOpt);
            var rewrittenBlock   = (BoundBlock)this.Visit(node.Body);

            return(node.Update(
                       rewrittenCatchLocal,
                       rewrittenExceptionSource,
                       exceptionTypeOpt,
                       rewrittenFilter,
                       rewrittenBlock));
        }
Ejemplo n.º 29
0
        /// <summary>
        /// The strategy of this rewrite is to do rewrite "locally".
        /// We analyze arguments of the concat in a shallow fashion assuming that
        /// lowering and optimizations (including this one) is already done for the arguments.
        /// Based on the arguments we select the most appropriate pattern for the current node.
        ///
        /// NOTE: it is not guaranteed that the node that we chose will be the most optimal since we have only
        ///       local information - i.e. we look at the arguments, but we do not know about siblings.
        ///       When we move to the parent, the node may be rewritten by this or some another optimization.
        ///
        /// Example:
        ///     result = ( "abc" + "def" + null ?? expr1 + "moo" + "baz" ) + expr2
        ///
        /// Will rewrite into:
        ///     result = Concat("abcdef", expr2)
        ///
        /// However there will be transient nodes like  Concat(expr1 + "moo")  that will not be present in the
        /// resulting tree.
        ///
        /// </summary>
        private BoundExpression RewriteStringConcatenation(SyntaxNode syntax, BinaryOperatorKind operatorKind, BoundExpression loweredLeft, BoundExpression loweredRight, TypeSymbol type)
        {
            Debug.Assert(
                operatorKind == BinaryOperatorKind.StringConcatenation ||
                operatorKind == BinaryOperatorKind.StringAndObjectConcatenation ||
                operatorKind == BinaryOperatorKind.ObjectAndStringConcatenation);

            if (_inExpressionLambda)
            {
                return(RewriteStringConcatInExpressionLambda(syntax, operatorKind, loweredLeft, loweredRight, type));
            }

            // avoid run time boxing and ToString operations if we can reasonably convert to a string at compile time
            loweredLeft  = ConvertConcatExprToStringIfPossible(syntax, loweredLeft);
            loweredRight = ConvertConcatExprToStringIfPossible(syntax, loweredRight);

            // try fold two args without flattening.
            var folded = TryFoldTwoConcatOperands(syntax, loweredLeft, loweredRight);

            if (folded != null)
            {
                return(folded);
            }

            // flatten and merge -  ( expr1 + "A" ) + ("B" + expr2) ===> (expr1 + "AB" + expr2)
            ArrayBuilder <BoundExpression> leftFlattened = ArrayBuilder <BoundExpression> .GetInstance();

            ArrayBuilder <BoundExpression> rightFlattened = ArrayBuilder <BoundExpression> .GetInstance();

            FlattenConcatArg(loweredLeft, leftFlattened);
            FlattenConcatArg(loweredRight, rightFlattened);

            if (leftFlattened.Any() && rightFlattened.Any())
            {
                folded = TryFoldTwoConcatOperands(syntax, leftFlattened.Last(), rightFlattened.First());
                if (folded != null)
                {
                    rightFlattened[0] = folded;
                    leftFlattened.RemoveLast();
                }
            }

            leftFlattened.AddRange(rightFlattened);
            rightFlattened.Free();

            BoundExpression result;

            switch (leftFlattened.Count)
            {
            case 0:
                result = _factory.StringLiteral(string.Empty);
                break;

            case 1:
                result = leftFlattened[0];
                break;

            case 2:
                var left  = leftFlattened[0];
                var right = leftFlattened[1];
                result = RewriteStringConcatenationTwoExprs(syntax, left, right);
                break;

            case 3:
                var first  = leftFlattened[0];
                var second = leftFlattened[1];
                var third  = leftFlattened[2];
                result = RewriteStringConcatenationThreeExprs(syntax, first, second, third);
                break;

            default:
                result = RewriteStringConcatenationManyExprs(syntax, leftFlattened.ToImmutable());
                break;
            }

            leftFlattened.Free();
            return(result);
        }
Ejemplo n.º 30
0
 private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> refKinds)
 {
     foreach (var refKind in refKinds)
     {
         if (refKind != RefKind.None)
         {
             return refKinds.ToImmutable();
         }
     }
     return default(ImmutableArray<RefKind>);
 }
Ejemplo n.º 31
0
        /// <summary>
        /// Get the import strings for a given method, following forward pointers as necessary.
        /// </summary>
        /// <returns>
        /// For each namespace enclosing the method, a list of import strings, innermost to outermost.
        /// There should always be at least one entry, for the global namespace.
        /// </returns>
        public static ImmutableArray <ImmutableArray <string> > GetCSharpGroupedImportStrings(this ISymUnmanagedReader reader, int methodToken, int methodVersion, out ImmutableArray <string> externAliasStrings)
        {
            externAliasStrings = default(ImmutableArray <string>);

            ImmutableArray <short> groupSizes = default(ImmutableArray <short>);
            bool seenForward = false;

RETRY:
            byte[] bytes = reader.GetCustomDebugInfo(methodToken, methodVersion);
            if (bytes == null)
            {
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            foreach (var record in GetCustomDebugInfoRecords(bytes))
            {
                switch (record.Kind)
                {
                case CustomDebugInfoKind.UsingInfo:
                    if (!groupSizes.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Expected at most one Using record for method {0}", FormatMethodToken(methodToken)));
                    }

                    groupSizes = DecodeUsingRecord(record.Data);
                    break;

                case CustomDebugInfoKind.ForwardInfo:
                    if (!externAliasStrings.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Did not expect both Forward and ForwardToModule records for method {0}", FormatMethodToken(methodToken)));
                    }

                    methodToken = DecodeForwardRecord(record.Data);

                    // Follow at most one forward link (as in FUNCBRECEE::ensureNamespaces).
                    // NOTE: Dev11 may produce chains of forward links (e.g. for System.Collections.Immutable).
                    if (!seenForward)
                    {
                        seenForward = true;
                        goto RETRY;
                    }

                    break;

                case CustomDebugInfoKind.ForwardToModuleInfo:
                    if (!externAliasStrings.IsDefault)
                    {
                        throw new InvalidOperationException(string.Format("Expected at most one ForwardToModule record for method {0}", FormatMethodToken(methodToken)));
                    }

                    int moduleInfoMethodToken = DecodeForwardToModuleRecord(record.Data);
                    ImmutableArray <string> allModuleInfoImportStrings = reader.GetMethodByVersion(moduleInfoMethodToken, methodVersion).GetImportStrings();
                    ArrayBuilder <string>   externAliasBuilder         = ArrayBuilder <string> .GetInstance();

                    foreach (string importString in allModuleInfoImportStrings)
                    {
                        if (IsCSharpExternAliasInfo(importString))
                        {
                            externAliasBuilder.Add(importString);
                        }
                    }

                    externAliasStrings = externAliasBuilder.ToImmutableAndFree();
                    break;
                }
            }

            if (groupSizes.IsDefault)
            {
                // This can happen in malformed PDBs (e.g. chains of forwards).
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            var method = reader.GetMethodByVersion(methodToken, methodVersion);

            if (method == null)
            {
                return(default(ImmutableArray <ImmutableArray <string> >));
            }

            ImmutableArray <string> importStrings = method.GetImportStrings();
            int numImportStrings = importStrings.Length;

            ArrayBuilder <ImmutableArray <string> > resultBuilder = ArrayBuilder <ImmutableArray <string> > .GetInstance(groupSizes.Length);

            ArrayBuilder <string> groupBuilder = ArrayBuilder <string> .GetInstance();

            int pos = 0;

            foreach (short groupSize in groupSizes)
            {
                for (int i = 0; i < groupSize; i++, pos++)
                {
                    if (pos >= numImportStrings)
                    {
                        throw new InvalidOperationException(string.Format("Group size indicates more imports than there are import strings (method {0}).", FormatMethodToken(methodToken)));
                    }

                    string importString = importStrings[pos];
                    if (IsCSharpExternAliasInfo(importString))
                    {
                        throw new InvalidOperationException(string.Format("Encountered extern alias info before all import strings were consumed (method {0}).", FormatMethodToken(methodToken)));
                    }

                    groupBuilder.Add(importString);
                }

                resultBuilder.Add(groupBuilder.ToImmutable());
                groupBuilder.Clear();
            }

            if (externAliasStrings.IsDefault)
            {
                Debug.Assert(groupBuilder.Count == 0);

                // Extern alias detail strings (prefix "Z") are not included in the group counts.
                for (; pos < numImportStrings; pos++)
                {
                    string importString = importStrings[pos];
                    if (!IsCSharpExternAliasInfo(importString))
                    {
                        throw new InvalidOperationException(string.Format("Expected only extern alias info strings after consuming the indicated number of imports (method {0}).", FormatMethodToken(methodToken)));
                    }

                    groupBuilder.Add(importString);
                }

                externAliasStrings = groupBuilder.ToImmutableAndFree();
            }
            else
            {
                groupBuilder.Free();

                if (pos < numImportStrings)
                {
                    throw new InvalidOperationException(string.Format("Group size indicates fewer imports than there are import strings (method {0}).", FormatMethodToken(methodToken)));
                }
            }

            return(resultBuilder.ToImmutableAndFree());
        }
Ejemplo n.º 32
0
        public override BoundNode VisitRangeExpression(BoundRangeExpression node)
        {
            Debug.Assert(node != null && node.MethodOpt != null);

            bool needLifting     = false;
            var  operandsBuilder = new ArrayBuilder <BoundExpression>();

            var left = node.LeftOperand;

            if (left != null)
            {
                operandsBuilder.Add(tryOptimizeOperand(left));
            }

            var right = node.RightOperand;

            if (right != null)
            {
                operandsBuilder.Add(tryOptimizeOperand(right));
            }

            ImmutableArray <BoundExpression> operands = operandsBuilder.ToImmutable();

            if (needLifting)
            {
                return(LiftRangeExpression(node, operands));
            }
            else
            {
                BoundExpression rangeCreation = MakeCall(
                    node.Syntax,
                    rewrittenReceiver: null,
                    node.MethodOpt,
                    operands,
                    node.MethodOpt.ReturnType.TypeSymbol);

                if (node.Type.IsNullableType())
                {
                    if (!TryGetNullableMethod(node.Syntax, node.Type, SpecialMember.System_Nullable_T__ctor, out MethodSymbol nullableCtor))
                    {
                        return(BadExpression(node.Syntax, node.Type, node));
                    }

                    return(new BoundObjectCreationExpression(node.Syntax, nullableCtor, binderOpt: null, rangeCreation));
                }

                return(rangeCreation);
            }

            BoundExpression tryOptimizeOperand(BoundExpression operand)
            {
                Debug.Assert(operand != null);
                operand = VisitExpression(operand);

                if (NullableNeverHasValue(operand))
                {
                    operand = new BoundDefaultExpression(operand.Syntax, operand.Type.GetNullableUnderlyingType());
                }
                else
                {
                    operand = NullableAlwaysHasValue(operand) ?? operand;

                    if (operand.Type.IsNullableType())
                    {
                        needLifting = true;
                    }
                }

                return(operand);
            }
        }