/// <summary> /// Marks blocks that are reachable. /// </summary> private void MarkReachableBlocks() { Debug.Assert(AllBlocks(block => (block.Reachability == Reachability.NotReachable))); ArrayBuilder <BasicBlock> reachableBlocks = ArrayBuilder <BasicBlock> .GetInstance(); MarkReachableFrom(reachableBlocks, leaderBlock); while (reachableBlocks.Count != 0) { MarkReachableFrom(reachableBlocks, reachableBlocks.Pop()); } reachableBlocks.Free(); }
private void EmitAllElementInitializersRecursive(ArrayTypeSymbol arrayType, ArrayBuilder<IndexDesc> indices, bool includeConstants) { var top = indices.Peek(); var inits = top.Initializers; if (IsMultidimensionalInitializer(inits)) { // emit initializers for the less significant indices recursively for (int i = 0; i < inits.Length; i++) { indices.Push(new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers)); EmitAllElementInitializersRecursive(arrayType, indices, includeConstants); } } else { // leaf case for (int i = 0; i < inits.Length; i++) { var init = inits[i]; if (ShouldEmitInitExpression(includeConstants, init)) { // emit array ref _builder.EmitOpCode(ILOpCode.Dup); Debug.Assert(indices.Count == arrayType.Rank - 1); // emit values of all indices that are in progress foreach (var row in indices) { _builder.EmitIntConstant(row.Index); } // emit the leaf index _builder.EmitIntConstant(i); var initExpr = inits[i]; EmitExpression(initExpr, true); EmitArrayElementStore(arrayType, init.Syntax); } } } indices.Pop(); }
/// <summary> /// Emits all initializers that match indices on the stack recursively. /// /// Example: /// if array has [0..2, 0..3, 0..2] shape /// and we have {1, 2} indices on the stack /// initializers for /// [1, 2, 0] /// [1, 2, 1] /// [1, 2, 2] /// /// will be emitted and the top index will be pushed off the stack /// as at that point we would be completely done with emitting initializers /// corresponding to that index. /// </summary> private void EmitAllElementInitializersRecursive(ArrayTypeSymbol arrayType, ArrayBuilder<IndexDesc> indices, bool includeConstants) { var top = indices.Peek(); var inits = top.Initializers; if (IsMultidimensionalInitializer(inits)) { // emit initializers for the less significant indices recursively for (int i = 0; i < inits.Length; i++) { indices.Push(new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers)); EmitAllElementInitializersRecursive(arrayType, indices, includeConstants); } } else { // leaf case for (int i = 0; i < inits.Length; i++) { var init = inits[i]; if (ShouldEmitInitExpression(includeConstants, init)) { // emit array ref _builder.EmitOpCode(ILOpCode.Dup); Debug.Assert(indices.Count == arrayType.Rank - 1); // emit values of all indices that are in progress foreach (var row in indices) { _builder.EmitIntConstant(row.Index); } // emit the leaf index _builder.EmitIntConstant(i); var initExpr = inits[i]; EmitExpression(initExpr, true); EmitArrayElementStore(arrayType, init.Syntax); } } } indices.Pop(); }
/// <summary> /// Determine if "type" inherits from or implements "baseType", ignoring constructed types, and dealing /// only with original types. /// </summary> private static bool InheritsFromOrImplementsIgnoringConstruction( this TypeSymbol type, NamedTypeSymbol baseType, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { Debug.Assert(type.IsDefinition); Debug.Assert(baseType.IsDefinition); PooledHashSet <NamedTypeSymbol> interfacesLookedAt = null; ArrayBuilder <NamedTypeSymbol> baseInterfaces = null; bool baseTypeIsInterface = baseType.IsInterface; if (baseTypeIsInterface) { interfacesLookedAt = PooledHashSet <NamedTypeSymbol> .GetInstance(); baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance(); } PooledHashSet <NamedTypeSymbol> visited = null; var current = type; bool result = false; while ((object)current != null) { Debug.Assert(current.IsDefinition); if (baseTypeIsInterface == current.IsInterfaceType() && current == (object)baseType) { result = true; break; } if (baseTypeIsInterface) { getBaseInterfaces(current, baseInterfaces, interfacesLookedAt, basesBeingResolved); } // NOTE(cyrusn): The base type of an 'original' type may not be 'original'. i.e. // "class Goo : IBar<int>". We must map it back to the 'original' when as we walk up // the base type hierarchy. var next = current.GetNextBaseTypeNoUseSiteDiagnostics(basesBeingResolved, compilation, ref visited); if ((object)next == null) { current = null; } else { current = (TypeSymbol)next.OriginalDefinition; current.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } visited?.Free(); if (!result && baseTypeIsInterface) { Debug.Assert(!result); while (baseInterfaces.Count != 0) { NamedTypeSymbol currentBase = baseInterfaces.Pop(); if (!currentBase.IsInterface) { continue; } Debug.Assert(currentBase.IsDefinition); if (currentBase == (object)baseType) { result = true; break; } getBaseInterfaces(currentBase, baseInterfaces, interfacesLookedAt, basesBeingResolved); } if (!result) { foreach (var candidate in interfacesLookedAt) { candidate.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } } interfacesLookedAt?.Free(); baseInterfaces?.Free(); return(result);
private BoundExpression MakeTupleCreationExpression(SyntaxNode syntax, NamedTypeSymbol type, ImmutableArray <BoundExpression> rewrittenArguments) { NamedTypeSymbol underlyingTupleType = type.TupleUnderlyingType ?? type; Debug.Assert(underlyingTupleType.IsTupleCompatible()); ArrayBuilder <NamedTypeSymbol> underlyingTupleTypeChain = ArrayBuilder <NamedTypeSymbol> .GetInstance(); TupleTypeSymbol.GetUnderlyingTypeChain(underlyingTupleType, underlyingTupleTypeChain); try { // make a creation expression for the smallest type NamedTypeSymbol smallestType = underlyingTupleTypeChain.Pop(); ImmutableArray <BoundExpression> smallestCtorArguments = ImmutableArray.Create(rewrittenArguments, underlyingTupleTypeChain.Count * (TupleTypeSymbol.RestPosition - 1), smallestType.Arity); var smallestCtor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(smallestType.OriginalDefinition, TupleTypeSymbol.GetTupleCtor(smallestType.Arity), _diagnostics, syntax); if ((object)smallestCtor == null) { return(_factory.BadExpression(type)); } MethodSymbol smallestConstructor = smallestCtor.AsMember(smallestType); BoundObjectCreationExpression currentCreation = new BoundObjectCreationExpression(syntax, smallestConstructor, null, smallestCtorArguments); if (underlyingTupleTypeChain.Count > 0) { NamedTypeSymbol tuple8Type = underlyingTupleTypeChain.Peek(); var tuple8Ctor = (MethodSymbol)TupleTypeSymbol.GetWellKnownMemberInType(tuple8Type.OriginalDefinition, TupleTypeSymbol.GetTupleCtor(TupleTypeSymbol.RestPosition), _diagnostics, syntax); if ((object)tuple8Ctor == null) { return(_factory.BadExpression(type)); } // make successively larger creation expressions containing the previous one do { ImmutableArray <BoundExpression> ctorArguments = ImmutableArray.Create(rewrittenArguments, (underlyingTupleTypeChain.Count - 1) * (TupleTypeSymbol.RestPosition - 1), TupleTypeSymbol.RestPosition - 1) .Add(currentCreation); MethodSymbol constructor = tuple8Ctor.AsMember(underlyingTupleTypeChain.Pop()); currentCreation = new BoundObjectCreationExpression(syntax, constructor, null, ctorArguments); }while (underlyingTupleTypeChain.Count > 0); } currentCreation = currentCreation.Update( currentCreation.Constructor, currentCreation.Arguments, currentCreation.ArgumentNamesOpt, currentCreation.ArgumentRefKindsOpt, currentCreation.Expanded, currentCreation.ArgsToParamsOpt, currentCreation.ConstantValue, currentCreation.InitializerExpressionOpt, currentCreation.BinderOpt, type); return(currentCreation); } finally { underlyingTupleTypeChain.Free(); } }
// Bucketing algorithm: // Start with empty stack of buckets. // While there are still labels // If bucket from remaining labels is dense // Create a newBucket from remaining labels // Else // Create a singleton newBucket from the next label // While the top bucket on stack can be merged with newBucket into a dense bucket // merge top bucket on stack into newBucket, and pop bucket from stack // End While // Push newBucket on stack // End While private ImmutableArray <SwitchBucket> GenerateSwitchBuckets(int startLabelIndex, int endLabelIndex) { Debug.Assert(startLabelIndex >= 0 && startLabelIndex <= endLabelIndex); Debug.Assert(_sortedCaseLabels.Length > endLabelIndex); // Start with empty stack of buckets. ArrayBuilder <SwitchBucket> switchBucketsStack = ArrayBuilder <SwitchBucket> .GetInstance(); int curStartLabelIndex = startLabelIndex; // While there are still labels while (curStartLabelIndex <= endLabelIndex) { SwitchBucket newBucket = CreateNextBucket(curStartLabelIndex, endLabelIndex); // While the top bucket on stack can be merged with newBucket into a dense bucket // merge top bucket on stack into newBucket, and pop bucket from stack // End While while (!switchBucketsStack.IsEmpty()) { // get the bucket at top of the stack SwitchBucket prevBucket = switchBucketsStack.Peek(); if (newBucket.TryMergeWith(prevBucket)) { // pop the previous bucket from the stack switchBucketsStack.Pop(); } else { // merge failed break; } } // Push newBucket on stack switchBucketsStack.Push(newBucket); // update curStartLabelIndex curStartLabelIndex++; } Debug.Assert(!switchBucketsStack.IsEmpty()); // crumble leaf buckets into degenerate buckets where possible ArrayBuilder <SwitchBucket> crumbled = ArrayBuilder <SwitchBucket> .GetInstance(); foreach (SwitchBucket uncrumbled in switchBucketsStack) { int degenerateSplit = uncrumbled.DegenerateBucketSplit; switch (degenerateSplit) { case -1: // cannot be split crumbled.Add(uncrumbled); break; case 0: // already degenerate crumbled.Add(new SwitchBucket(_sortedCaseLabels, uncrumbled.StartLabelIndex, uncrumbled.EndLabelIndex, isDegenerate: true)); break; default: // can split crumbled.Add(new SwitchBucket(_sortedCaseLabels, uncrumbled.StartLabelIndex, degenerateSplit - 1, isDegenerate: true)); crumbled.Add(new SwitchBucket(_sortedCaseLabels, degenerateSplit, uncrumbled.EndLabelIndex, isDegenerate: true)); break; } } switchBucketsStack.Free(); return(crumbled.ToImmutableAndFree()); }