public SwitchSection(BoundSwitchSection boundNode) { this.Body = boundNode.Statements.As <IOperation>(); this.Clauses = boundNode.BoundSwitchLabels.As <ICaseClause>(); this.IsInvalid = boundNode.HasErrors; this.Syntax = boundNode.Syntax; }
public override BoundNode VisitSwitchSection(BoundSwitchSection node) { AddAll(node.Locals); base.VisitSwitchSection(node); RemoveAll(node.Locals); return(null); }
protected override void VisitSwitchSectionLabel(LabelSymbol label, BoundSwitchSection node) { _labelsDefined.Add(label); base.VisitSwitchSectionLabel(label, node); // switch statement labels are always considered to be referenced _labelsUsed.Add(label); }
protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastSection) { foreach (var label in node.SwitchLabels) { NoteDeclaredPatternVariables(label.Pattern); } base.VisitSwitchSection(node, isLastSection); }
protected virtual void VisitSwitchSection(BoundSwitchSection node, bool isLastSection) { SetState(UnreachableState()); foreach (var label in node.SwitchLabels) { VisitLabel(label.Label, node); } VisitStatementList(node); }
protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastSection) { TakeIncrementalSnapshot(node); SetState(UnreachableState()); foreach (var label in node.SwitchLabels) { TakeIncrementalSnapshot(label); VisitLabel(label.Label, node); } VisitStatementList(node); }
protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastSection) { base.VisitSwitchSection(node, isLastSection); // Check for switch section fall through error if (this.State.Alive) { var syntax = node.SwitchLabels.Last().Pattern.Syntax; Diagnostics.Add(isLastSection ? ErrorCode.ERR_SwitchFallOut : ErrorCode.ERR_SwitchFallThrough, new SourceLocation(syntax), syntax.ToString()); } }
public override BoundNode VisitSwitchSection(BoundSwitchSection node) { // visit switch section labels foreach (var boundSwitchLabel in node.SwitchLabels) { VisitRvalue(boundSwitchLabel.ExpressionOpt); VisitSwitchSectionLabel(boundSwitchLabel.Label, node); } // visit switch section body VisitStatementList(node); return(null); }
public override BoundNode VisitSwitchSection(BoundSwitchSection node, bool lastSection) { base.VisitSwitchSection(node); // Check for switch section fall through error if (this.State.Alive) { Debug.Assert(node.SwitchLabels.Any()); var boundLabel = node.SwitchLabels.Last(); Diagnostics.Add(lastSection ? ErrorCode.ERR_SwitchFallOut : ErrorCode.ERR_SwitchFallThrough, new SourceLocation(boundLabel.Syntax), boundLabel.Label.Name); } return(null); }
public override BoundNode VisitSwitchSection(BoundSwitchSection node) { return(node.Update(VisitList(node.BoundSwitchLabels), VisitList(node.Statements))); }
public override BoundNode VisitSwitchSection(BoundSwitchSection node) { return node.Update(VisitList(node.BoundSwitchLabels), VisitList(node.Statements)); }
private void VisitSwitchSectionLabel(LabelSymbol label, BoundSwitchSection node) { VisitLabel(label, node); }
public virtual BoundNode VisitSwitchSection(BoundSwitchSection node, bool lastSection) { return(VisitSwitchSection(node)); }
protected virtual void VisitSwitchSectionLabel(LabelSymbol label, BoundSwitchSection node) { VisitLabel(label, node); }
public SwitchSection(BoundSwitchSection boundNode) { this.Body = boundNode.Statements.As<IStatement>(); this.Clauses = boundNode.BoundSwitchLabels.As<ICaseClause>(); this.IsInvalid = boundNode.HasErrors; this.Syntax = boundNode.Syntax; }
public override BoundNode VisitSwitchSection(BoundSwitchSection node) { Debug.Assert(node.Locals.IsEmpty); return(node.Update(locals: node.Locals, VisitList(node.SwitchLabels), VisitList(node.Statements))); }
// For switch statements, we have an option of completely rewriting the switch header // and switch sections into simpler constructs, i.e. we can rewrite the switch header // using bound conditional goto statements and the rewrite the switch sections into // bound labeled statements. // // However, all the logic for emitting the switch jump tables is language agnostic // and includes IL optimizations. Hence we delay the switch jump table generation // till the emit phase. This way we also get additional benefit of sharing this code // between both VB and C# compilers. // // For string switch statements, we need to determine if we are generating a hash // table based jump table or a non hash jump table, i.e. linear string comparisons // with each case label. We use the Dev10 Heuristic to determine this // (see SwitchStringJumpTableEmitter.ShouldGenerateHashTableSwitch() for details). // If we are generating a hash table based jump table, we use a simple // hash function to hash the string constants corresponding to the case labels. // See SwitchStringJumpTableEmitter.ComputeStringHash(). // We need to emit this same function to compute the hash value into the compiler generated // <PrivateImplementationDetails> class. // If we have at least one string switch statement in a module that needs a // hash table based jump table, we generate a single public string hash synthesized method // that is shared across the module. private void LowerBasicSwitch(DecisionTree.ByValue byValue) { var switchSections = ArrayBuilder <BoundSwitchSection> .GetInstance(); var noValueMatches = _factory.GenerateLabel("noValueMatches"); var underlyingSwitchType = byValue.Type.IsEnumType() ? byValue.Type.GetEnumUnderlyingType() : byValue.Type; foreach (var vd in byValue.ValueAndDecision) { var value = vd.Key; var decision = vd.Value; var constantValue = ConstantValue.Create(value, underlyingSwitchType.SpecialType); var constantExpression = new BoundLiteral(_factory.Syntax, constantValue, underlyingSwitchType); var label = _factory.GenerateLabel("case+" + value); var switchLabel = new BoundSwitchLabel(_factory.Syntax, label, constantExpression, constantValue); var forValue = ArrayBuilder <BoundStatement> .GetInstance(); LowerDecisionTree(byValue.Expression, decision, forValue); if (!decision.MatchIsComplete) { forValue.Add(_factory.Goto(noValueMatches)); } var section = new BoundSwitchSection(_factory.Syntax, ImmutableArray.Create(switchLabel), forValue.ToImmutableAndFree()); switchSections.Add(section); } var rewrittenSections = switchSections.ToImmutableAndFree(); MethodSymbol stringEquality = null; if (underlyingSwitchType.SpecialType == SpecialType.System_String) { _localRewriter.EnsureStringHashFunction(rewrittenSections, _factory.Syntax); stringEquality = _localRewriter.UnsafeGetSpecialTypeMethod(_factory.Syntax, SpecialMember.System_String__op_Equality); } // The BoundSwitchStatement requires a constant target when there are no sections, so we accomodate that here. var constantTarget = rewrittenSections.IsEmpty ? noValueMatches : null; var switchStatement = new BoundSwitchStatement( _factory.Syntax, null, _factory.Convert(underlyingSwitchType, byValue.Expression), constantTarget, ImmutableArray <LocalSymbol> .Empty, ImmutableArray <LocalFunctionSymbol> .Empty, rewrittenSections, noValueMatches, stringEquality); // The bound switch statement implicitly defines the label noValueMatches at the end, so we do not add it explicitly. switch (underlyingSwitchType.SpecialType) { case SpecialType.System_Boolean: // boolean switch is handled in LowerBooleanSwitch, not here. throw ExceptionUtilities.Unreachable; case SpecialType.System_String: case SpecialType.System_Byte: case SpecialType.System_Char: case SpecialType.System_Int16: case SpecialType.System_Int32: case SpecialType.System_Int64: case SpecialType.System_SByte: case SpecialType.System_UInt16: case SpecialType.System_UInt32: case SpecialType.System_UInt64: { // emit knows how to efficiently generate code for these kinds of switches. _loweredDecisionTree.Add(switchStatement); break; } default: { // other types, such as float, double, and decimal, are not currently // handled by emit and must be lowered here. _loweredDecisionTree.Add(LowerNonprimitiveSwitch(switchStatement)); break; } } LowerDecisionTree(byValue.Expression, byValue.Default); }
// For switch statements, we have an option of completely rewriting the switch header // and switch sections into simpler constructs, i.e. we can rewrite the switch header // using bound conditional goto statements and the rewrite the switch sections into // bound labeled statements. // // However, all the logic for emitting the switch jump tables is language agnostic // and includes IL optimizations. Hence we delay the switch jump table generation // till the emit phase. This way we also get additional benefit of sharing this code // between both VB and C# compilers. // // For string switch statements, we need to determine if we are generating a hash // table based jump table or a non hash jump table, i.e. linear string comparisons // with each case label. We use the Dev10 Heuristic to determine this // (see SwitchStringJumpTableEmitter.ShouldGenerateHashTableSwitch() for details). // If we are generating a hash table based jump table, we use a simple // hash function to hash the string constants corresponding to the case labels. // See SwitchStringJumpTableEmitter.ComputeStringHash(). // We need to emit this same function to compute the hash value into the compiler generated // <PrivateImplementationDetails> class. // If we have at least one string switch statement in a module that needs a // hash table based jump table, we generate a single public string hash synthesized method // that is shared across the module. private void LowerBasicSwitch(DecisionTree.ByValue byValue) { var switchSections = ArrayBuilder<BoundSwitchSection>.GetInstance(); var noValueMatches = _factory.GenerateLabel("noValueMatches"); var underlyingSwitchType = byValue.Type.IsEnumType() ? byValue.Type.GetEnumUnderlyingType() : byValue.Type; foreach (var vd in byValue.ValueAndDecision) { var value = vd.Key; var decision = vd.Value; var constantValue = ConstantValue.Create(value, underlyingSwitchType.SpecialType); var constantExpression = new BoundLiteral(_factory.Syntax, constantValue, underlyingSwitchType); var label = _factory.GenerateLabel("case+" + value); var switchLabel = new BoundSwitchLabel(_factory.Syntax, label, constantExpression, constantValue); var forValue = ArrayBuilder<BoundStatement>.GetInstance(); LowerDecisionTree(byValue.Expression, decision, forValue); if (!decision.MatchIsComplete) { forValue.Add(_factory.Goto(noValueMatches)); } var section = new BoundSwitchSection(_factory.Syntax, ImmutableArray.Create(switchLabel), forValue.ToImmutableAndFree()); switchSections.Add(section); } var rewrittenSections = switchSections.ToImmutableAndFree(); MethodSymbol stringEquality = null; if (underlyingSwitchType.SpecialType == SpecialType.System_String) { LocalRewriter.EnsureStringHashFunction(rewrittenSections, _factory.Syntax); stringEquality = LocalRewriter.GetSpecialTypeMethod(_factory.Syntax, SpecialMember.System_String__op_Equality); } // The BoundSwitchStatement requires a constant target when there are no sections, so we accomodate that here. var constantTarget = rewrittenSections.IsEmpty ? noValueMatches : null; var switchStatement = new BoundSwitchStatement( _factory.Syntax, null, _factory.Convert(underlyingSwitchType, byValue.Expression), constantTarget, ImmutableArray<LocalSymbol>.Empty, ImmutableArray<LocalFunctionSymbol>.Empty, rewrittenSections, noValueMatches, stringEquality); // The bound switch statement implicitly defines the label noValueMatches at the end, so we do not add it explicitly. switch (underlyingSwitchType.SpecialType) { case SpecialType.System_Boolean: // boolean switch is handled in LowerBooleanSwitch, not here. throw ExceptionUtilities.Unreachable; case SpecialType.System_String: case SpecialType.System_Byte: case SpecialType.System_Char: case SpecialType.System_Int16: case SpecialType.System_Int32: case SpecialType.System_Int64: case SpecialType.System_SByte: case SpecialType.System_UInt16: case SpecialType.System_UInt32: case SpecialType.System_UInt64: { // emit knows how to efficiently generate code for these kinds of switches. _loweredDecisionTree.Add(switchStatement); break; } default: { // other types, such as float, double, and decimal, are not currently // handled by emit and must be lowered here. _loweredDecisionTree.Add(LowerNonprimitiveSwitch(switchStatement)); break; } } LowerDecisionTree(byValue.Expression, byValue.Default); }