/// <summary> /// Rewrites Try/Catch part of the Try/Catch/Finally /// </summary> private Statement RewriteFinalizedRegion(TryStatement node) { var rewrittenTry = (Block)Visit(node.ProtectedBlock); var catches = node.ExceptionHandlers; if (catches.IsEmpty) { return(rewrittenTry); } var origAwaitCatchFrame = _currentAwaitCatchFrame; _currentAwaitCatchFrame = null; Visit(node.ExceptionHandlers); Statement tryWithCatches = new TryStatement { EnsureBlock = rewrittenTry }; ((TryStatement)tryWithCatches).ExceptionHandlers = node.ExceptionHandlers; var currentAwaitCatchFrame = _currentAwaitCatchFrame; if (currentAwaitCatchFrame != null) { var handledLabel = _F.CreateLabel(tryWithCatches, CompilerContext.Current.GetUniqueName("handled"), _tryDepth); var handlersList = currentAwaitCatchFrame.handlers; _tryDepth = node.GetAncestors <TryStatement>().Count() + 1; var handlers = new List <Statement> { _F.CreateGoto(handledLabel, _tryDepth) }; for (int i = 0, l = handlersList.Count; i < l; i++) { handlers.Add( new Block( handlersList[i], _F.CreateGoto(handledLabel, _tryDepth))); } _containingMethod.Locals.Add(currentAwaitCatchFrame.pendingCaughtException.Local); _containingMethod.Locals.Add(currentAwaitCatchFrame.pendingCatch.Local); _containingMethod.Locals.AddRange(currentAwaitCatchFrame.GetHoistedLocals().Select(l => l.Local)); tryWithCatches = new Block( new ExpressionStatement( _F.CreateAssignment( _F.CreateLocalReference(currentAwaitCatchFrame.pendingCatch), _F.CreateDefaultInvocation(LexicalInfo.Empty, currentAwaitCatchFrame.pendingCatch.Type))), tryWithCatches, CreateSwitch(handlers, handledLabel, currentAwaitCatchFrame.pendingCatch)); } _currentAwaitCatchFrame = origAwaitCatchFrame; return(tryWithCatches); }
/// <summary> /// Rewrites Try/Catch part of the Try/Catch/Finally /// </summary> private BoundStatement RewriteFinalizedRegion(BoundTryStatement node) { var rewrittenTry = (BoundBlock)this.VisitBlock(node.TryBlock); var catches = node.CatchBlocks; if (catches.IsDefaultOrEmpty) { return(rewrittenTry); } var origAwaitCatchFrame = _currentAwaitCatchFrame; _currentAwaitCatchFrame = null; var rewrittenCatches = this.VisitList(node.CatchBlocks); BoundStatement tryWithCatches = _F.Try(rewrittenTry, rewrittenCatches); var currentAwaitCatchFrame = _currentAwaitCatchFrame; if (currentAwaitCatchFrame != null) { var handledLabel = _F.GenerateLabel("handled"); var handlersList = currentAwaitCatchFrame.handlers; var handlers = ArrayBuilder <BoundSwitchSection> .GetInstance(handlersList.Count); for (int i = 0, l = handlersList.Count; i < l; i++) { handlers.Add(_F.SwitchSection( i + 1, _F.Block( handlersList[i], _F.Goto(handledLabel)))); } tryWithCatches = _F.Block( ImmutableArray.Create <LocalSymbol>( currentAwaitCatchFrame.pendingCaughtException, currentAwaitCatchFrame.pendingCatch). AddRange(currentAwaitCatchFrame.GetHoistedLocals()), _F.HiddenSequencePoint(), _F.Assignment( _F.Local(currentAwaitCatchFrame.pendingCatch), _F.Default(currentAwaitCatchFrame.pendingCatch.Type.TypeSymbol)), tryWithCatches, _F.HiddenSequencePoint(), _F.Switch( _F.Local(currentAwaitCatchFrame.pendingCatch), handlers.ToImmutableAndFree()), _F.HiddenSequencePoint(), _F.Label(handledLabel)); } _currentAwaitCatchFrame = origAwaitCatchFrame; return(tryWithCatches); }
private BoundExpression AssignCatchSource(BoundExpression rewrittenSource, AwaitCatchFrame currentAwaitCatchFrame) { BoundExpression assignSource = null; if (rewrittenSource != null) { // exceptionSource = (exceptionSourceType)pendingCaughtException; assignSource = _F.AssignmentExpression( rewrittenSource, _F.Convert( rewrittenSource.Type, _F.Local(currentAwaitCatchFrame.pendingCaughtException))); } return(assignSource); }
private Expression AssignCatchSource(Declaration rewrittenSource, AwaitCatchFrame currentAwaitCatchFrame) { Expression assignSource = null; if (rewrittenSource != null) { // exceptionSource = (exceptionSourceType)pendingCaughtException; assignSource = _F.CreateAssignment( _F.CreateLocalReference((InternalLocal)rewrittenSource.Entity), _F.CreateCast( (IType)rewrittenSource.Type.Entity, _F.CreateLocalReference(currentAwaitCatchFrame.pendingCaughtException))); } return(assignSource); }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (!_analysis.CatchContainsAwait(node)) { var origCurrentAwaitCatchFrame = _currentAwaitCatchFrame; _currentAwaitCatchFrame = null; var result = base.VisitCatchBlock(node); _currentAwaitCatchFrame = origCurrentAwaitCatchFrame; return(result); } var currentAwaitCatchFrame = _currentAwaitCatchFrame; if (currentAwaitCatchFrame == null) { Debug.Assert(node.Syntax.IsKind(SyntaxKind.CatchClause)); var tryStatementSyntax = (TryStatementSyntax)node.Syntax.Parent; currentAwaitCatchFrame = _currentAwaitCatchFrame = new AwaitCatchFrame(_F, tryStatementSyntax); } var catchType = node.ExceptionTypeOpt ?? _F.SpecialType(SpecialType.System_Object); var catchTemp = _F.SynthesizedLocal(catchType); var storePending = _F.AssignmentExpression( _F.Local(currentAwaitCatchFrame.pendingCaughtException), _F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type.TypeSymbol, _F.Local(catchTemp))); var setPendingCatchNum = _F.Assignment( _F.Local(currentAwaitCatchFrame.pendingCatch), _F.Literal(currentAwaitCatchFrame.handlers.Count + 1)); // catch (ExType exTemp) // { // pendingCaughtException = exTemp; // catchNo = X; // } BoundCatchBlock catchAndPend; ImmutableArray <LocalSymbol> handlerLocals; var filterOpt = node.ExceptionFilterOpt; if (filterOpt == null) { // store pending exception // as the first statement in a catch catchAndPend = node.Update( ImmutableArray.Create(catchTemp), _F.Local(catchTemp), catchType, exceptionFilterOpt: null, body: _F.Block( _F.HiddenSequencePoint(), _F.ExpressionStatement(storePending), setPendingCatchNum), isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll); // catch locals live on the synthetic catch handler block handlerLocals = node.Locals; } else { handlerLocals = ImmutableArray <LocalSymbol> .Empty; // catch locals move up into hoisted locals // since we might need to access them from both the filter and the catch foreach (var local in node.Locals) { currentAwaitCatchFrame.HoistLocal(local, _F); } // store pending exception // as the first expression in a filter var sourceOpt = node.ExceptionSourceOpt; var rewrittenFilter = (BoundExpression)this.Visit(filterOpt); var newFilter = sourceOpt == null? _F.MakeSequence( storePending, rewrittenFilter) : _F.MakeSequence( storePending, AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame), rewrittenFilter); catchAndPend = node.Update( ImmutableArray.Create(catchTemp), _F.Local(catchTemp), catchType, exceptionFilterOpt: newFilter, body: _F.Block( _F.HiddenSequencePoint(), setPendingCatchNum), isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll); } var handlerStatements = ArrayBuilder <BoundStatement> .GetInstance(); handlerStatements.Add(_F.HiddenSequencePoint()); if (filterOpt == null) { var sourceOpt = node.ExceptionSourceOpt; if (sourceOpt != null) { BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame); handlerStatements.Add(_F.ExpressionStatement(assignSource)); } } handlerStatements.Add((BoundStatement)this.Visit(node.Body)); var handler = _F.Block( handlerLocals, handlerStatements.ToImmutableAndFree() ); currentAwaitCatchFrame.handlers.Add(handler); return(catchAndPend); }
private BoundExpression AssignCatchSource(BoundExpression rewrittenSource, AwaitCatchFrame currentAwaitCatchFrame) { BoundExpression assignSource = null; if (rewrittenSource != null) { // exceptionSource = (exceptionSourceType)pendingCaughtException; assignSource = _F.AssignmentExpression( rewrittenSource, _F.Convert( rewrittenSource.Type, _F.Local(currentAwaitCatchFrame.pendingCaughtException))); } return assignSource; }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (!_analysis.CatchContainsAwait(node)) { var origCurrentAwaitCatchFrame = _currentAwaitCatchFrame; _currentAwaitCatchFrame = null; var result = base.VisitCatchBlock(node); _currentAwaitCatchFrame = origCurrentAwaitCatchFrame; return result; } var currentAwaitCatchFrame = _currentAwaitCatchFrame; if (currentAwaitCatchFrame == null) { Debug.Assert(node.Syntax.IsKind(SyntaxKind.CatchClause)); var tryStatementSyntax = (TryStatementSyntax)node.Syntax.Parent; currentAwaitCatchFrame = _currentAwaitCatchFrame = new AwaitCatchFrame(_F, tryStatementSyntax); } var catchType = node.ExceptionTypeOpt ?? _F.SpecialType(SpecialType.System_Object); var catchTemp = _F.SynthesizedLocal(catchType); var storePending = _F.AssignmentExpression( _F.Local(currentAwaitCatchFrame.pendingCaughtException), _F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type, _F.Local(catchTemp))); var setPendingCatchNum = _F.Assignment( _F.Local(currentAwaitCatchFrame.pendingCatch), _F.Literal(currentAwaitCatchFrame.handlers.Count + 1)); // catch (ExType exTemp) // { // pendingCaughtException = exTemp; // catchNo = X; // } BoundCatchBlock catchAndPend; var handlerLocals = ImmutableArray<LocalSymbol>.Empty; var filterOpt = node.ExceptionFilterOpt; if (filterOpt == null) { // store pending exception // as the first statement in a catch catchAndPend = node.Update( catchTemp, _F.Local(catchTemp), catchType, exceptionFilterOpt: null, body: _F.Block( _F.HiddenSequencePoint(), _F.ExpressionStatement(storePending), setPendingCatchNum), isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll); // catch locals live on the synthetic catch handler block if ((object)node.LocalOpt != null) { handlerLocals = ImmutableArray.Create(node.LocalOpt); } } else { // catch locals move up into hoisted locals // since we might need to access them from both the filter and the catch if ((object)node.LocalOpt != null) { currentAwaitCatchFrame.HoistLocal(node.LocalOpt, _F); } // store pending exception // as the first expression in a filter var sourceOpt = node.ExceptionSourceOpt; var rewrittenFilter = (BoundExpression)this.Visit(filterOpt); var newFilter = sourceOpt == null ? _F.Sequence( storePending, rewrittenFilter) : _F.Sequence( storePending, AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame), rewrittenFilter); catchAndPend = node.Update( catchTemp, _F.Local(catchTemp), catchType, exceptionFilterOpt: newFilter, body: _F.Block( _F.HiddenSequencePoint(), setPendingCatchNum), isSynthesizedAsyncCatchAll: node.IsSynthesizedAsyncCatchAll); } var handlerStatements = ArrayBuilder<BoundStatement>.GetInstance(); handlerStatements.Add(_F.HiddenSequencePoint()); if (filterOpt == null) { var sourceOpt = node.ExceptionSourceOpt; if (sourceOpt != null) { BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame); handlerStatements.Add(_F.ExpressionStatement(assignSource)); } } handlerStatements.Add((BoundStatement)this.Visit(node.Body)); var handler = _F.Block( handlerLocals, ImmutableArray<LocalFunctionSymbol>.Empty, handlerStatements.ToImmutableAndFree() ); currentAwaitCatchFrame.handlers.Add(handler); return catchAndPend; }
/// <summary> /// Rewrites Try/Catch part of the Try/Catch/Finally /// </summary> private BoundStatement RewriteFinalizedRegion(BoundTryStatement node) { var rewrittenTry = (BoundBlock)this.VisitBlock(node.TryBlock); var catches = node.CatchBlocks; if (catches.IsDefaultOrEmpty) { return rewrittenTry; } var origAwaitCatchFrame = _currentAwaitCatchFrame; _currentAwaitCatchFrame = null; var rewrittenCatches = this.VisitList(node.CatchBlocks); BoundStatement tryWithCatches = _F.Try(rewrittenTry, rewrittenCatches); var currentAwaitCatchFrame = _currentAwaitCatchFrame; if (currentAwaitCatchFrame != null) { var handledLabel = _F.GenerateLabel("handled"); var handlersList = currentAwaitCatchFrame.handlers; var handlers = ArrayBuilder<BoundSwitchSection>.GetInstance(handlersList.Count); for (int i = 0, l = handlersList.Count; i < l; i++) { handlers.Add(_F.SwitchSection( i + 1, _F.Block( handlersList[i], _F.Goto(handledLabel)))); } tryWithCatches = _F.Block( ImmutableArray.Create<LocalSymbol>( currentAwaitCatchFrame.pendingCaughtException, currentAwaitCatchFrame.pendingCatch). AddRange(currentAwaitCatchFrame.GetHoistedLocals()), ImmutableArray<LocalFunctionSymbol>.Empty, _F.HiddenSequencePoint(), _F.Assignment( _F.Local(currentAwaitCatchFrame.pendingCatch), _F.Default(currentAwaitCatchFrame.pendingCatch.Type)), tryWithCatches, _F.HiddenSequencePoint(), _F.Switch( _F.Local(currentAwaitCatchFrame.pendingCatch), handlers.ToImmutableAndFree()), _F.HiddenSequencePoint(), _F.Label(handledLabel)); } _currentAwaitCatchFrame = origAwaitCatchFrame; return tryWithCatches; }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (!analysis.CatchContainsAwait(node)) { return (BoundCatchBlock)base.VisitCatchBlock(node); } var currentAwaitCatchFrame = this.currentAwaitCatchFrame; if (currentAwaitCatchFrame == null) { currentAwaitCatchFrame = this.currentAwaitCatchFrame = new AwaitCatchFrame(F); } var catchType = node.ExceptionTypeOpt ?? F.SpecialType(SpecialType.System_Object); var catchTemp = F.SynthesizedLocal(catchType); var storePending = F.AssignmentExpression( F.Local(currentAwaitCatchFrame.pendingCaughtException), F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type, F.Local(catchTemp))); var setPendingCatchNum = F.Assignment( F.Local(currentAwaitCatchFrame.pendingCatch), F.Literal(currentAwaitCatchFrame.handlers.Count + 1)); // catch (ExType exTemp) // { // pendingCaughtException = exTemp; // catchNo = X; // } BoundCatchBlock catchAndPend; ImmutableArray<LocalSymbol> handlerLocals; var filterOpt = node.ExceptionFilterOpt; if (filterOpt == null) { // store pending exception // as the first statement in a catch catchAndPend = node.Update( catchTemp, F.Local(catchTemp), catchType, exceptionFilterOpt: null, body: F.Block( F.HiddenSequencePoint(), F.ExpressionStatement(storePending), setPendingCatchNum)); // catch local lives on the synthetic catch handler block handlerLocals = node.LocalOpt == null ? ImmutableArray<LocalSymbol>.Empty : ImmutableArray.Create(node.LocalOpt); } else { // catch local moves up into hoisted locals // since we might need to access it from both the filter and the catch handlerLocals = ImmutableArray<LocalSymbol>.Empty; if (node.LocalOpt != null) { currentAwaitCatchFrame.HoistLocal(node.LocalOpt, F); } // store pending exception // as the first expression in a filter var sourceOpt = node.ExceptionSourceOpt; var rewrittenFilter = (BoundExpression)this.Visit(filterOpt); var newFilter = sourceOpt == null ? F.Sequence( storePending, rewrittenFilter) : F.Sequence( storePending, AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame), rewrittenFilter); catchAndPend = node.Update( catchTemp, F.Local(catchTemp), catchType, exceptionFilterOpt: newFilter, body: F.Block( F.HiddenSequencePoint(), setPendingCatchNum)); } var handlerStatements = ArrayBuilder<BoundStatement>.GetInstance(); handlerStatements.Add(F.HiddenSequencePoint()); if (filterOpt == null) { var sourceOpt = node.ExceptionSourceOpt; if (sourceOpt != null) { BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame); handlerStatements.Add(F.ExpressionStatement(assignSource)); } } handlerStatements.Add((BoundStatement)this.Visit(node.Body)); var handler = F.Block( handlerLocals, handlerStatements.ToImmutableAndFree() ); currentAwaitCatchFrame.handlers.Add(handler); return catchAndPend; }
public override void OnExceptionHandler(ExceptionHandler node) { if (!_analysis.CatchContainsAwait(node)) { var origCurrentAwaitCatchFrame = _currentAwaitCatchFrame; _currentAwaitCatchFrame = null; var result = Visit(node); _currentAwaitCatchFrame = origCurrentAwaitCatchFrame; ReplaceCurrentNode(result); } var currentAwaitCatchFrame = _currentAwaitCatchFrame ?? (_currentAwaitCatchFrame = new AwaitCatchFrame(_tss, _F, _containingMethod)); var catchType = node.Declaration != null ? (IType)node.Declaration.Type.Entity : _tss.ObjectType; var catchTemp = _F.DeclareTempLocal(_containingMethod, catchType); var storePending = _F.CreateAssignment( _F.CreateLocalReference(currentAwaitCatchFrame.pendingCaughtException), _F.CreateCast(currentAwaitCatchFrame.pendingCaughtException.Type, _F.CreateLocalReference(catchTemp))); var setPendingCatchNum = _F.CreateAssignment( _F.CreateLocalReference(currentAwaitCatchFrame.pendingCatch), _F.CreateIntegerLiteral(currentAwaitCatchFrame.handlers.Count + 1)); // catch (ExType exTemp) // { // pendingCaughtException = exTemp; // catchNo = X; // } ExceptionHandler catchAndPend; var filterOpt = node.FilterCondition; if (filterOpt == null) { // store pending exception // as the first statement in a catch catchAndPend = new ExceptionHandler { Declaration = new Declaration(catchTemp.Name, _F.CreateTypeReference(catchType)) { Entity = catchTemp }, Block = new Block( new ExpressionStatement(storePending), new ExpressionStatement(setPendingCatchNum)) }; // catch locals live on the synthetic catch handler block } else { // catch locals move up into hoisted locals // since we might need to access them from both the filter and the catch foreach (var local in LocalsUsedIn(node)) { currentAwaitCatchFrame.HoistLocal(local, _F); } // store pending exception // as the first expression in a filter var decl = node.Declaration; var sourceOpt = decl != null && !string.IsNullOrEmpty(decl.Name) ? decl : null; var rewrittenFilter = Visit(filterOpt); var newFilter = sourceOpt == null? _F.CreateEvalInvocation( storePending.LexicalInfo, storePending, rewrittenFilter) : _F.CreateEvalInvocation( storePending.LexicalInfo, storePending, AssignCatchSource((Declaration)Visit(sourceOpt), currentAwaitCatchFrame), rewrittenFilter); catchAndPend = new ExceptionHandler { Declaration = new Declaration(catchTemp.Name, _F.CreateTypeReference(catchType)) { Entity = catchTemp }, FilterCondition = newFilter, Block = new Block(new ExpressionStatement(setPendingCatchNum)) }; } if (node.ContainsAnnotation("isSynthesizedAsyncCatchAll")) { catchAndPend.Annotate("isSynthesizedAsyncCatchAll"); } var handlerStatements = new List <Statement>(); if (filterOpt == null) { var sourceOpt = node.Declaration; if (sourceOpt != null && sourceOpt.Entity != null) { Expression assignSource = AssignCatchSource((Declaration)Visit(sourceOpt), currentAwaitCatchFrame); handlerStatements.Add(new ExpressionStatement(assignSource)); } } handlerStatements.Add(Visit(node.Block)); var handler = new Block(handlerStatements.ToArray()); currentAwaitCatchFrame.handlers.Add(handler); ReplaceCurrentNode(catchAndPend); }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (!analysis.CatchContainsAwait(node)) { return((BoundCatchBlock)base.VisitCatchBlock(node)); } var currentAwaitCatchFrame = this.currentAwaitCatchFrame; if (currentAwaitCatchFrame == null) { currentAwaitCatchFrame = this.currentAwaitCatchFrame = new AwaitCatchFrame(F); } var catchType = node.ExceptionTypeOpt ?? F.SpecialType(SpecialType.System_Object); var catchTemp = F.SynthesizedLocal(catchType); var storePending = F.AssignmentExpression( F.Local(currentAwaitCatchFrame.pendingCaughtException), F.Convert(currentAwaitCatchFrame.pendingCaughtException.Type, F.Local(catchTemp))); var setPendingCatchNum = F.Assignment( F.Local(currentAwaitCatchFrame.pendingCatch), F.Literal(currentAwaitCatchFrame.handlers.Count + 1)); // catch (ExType exTemp) // { // pendingCaughtException = exTemp; // catchNo = X; // } BoundCatchBlock catchAndPend; ImmutableArray <LocalSymbol> handlerLocals; var filterOpt = node.ExceptionFilterOpt; if (filterOpt == null) { // store pending exception // as the first statement in a catch catchAndPend = node.Update( catchTemp, F.Local(catchTemp), catchType, exceptionFilterOpt: null, body: F.Block( F.HiddenSequencePoint(), F.ExpressionStatement(storePending), setPendingCatchNum)); // catch local lives on the synthetic catch handler block handlerLocals = node.LocalOpt == null ? ImmutableArray <LocalSymbol> .Empty : ImmutableArray.Create(node.LocalOpt); } else { // catch local moves up into hoisted locals // since we might need to access it from both the filter and the catch handlerLocals = ImmutableArray <LocalSymbol> .Empty; if (node.LocalOpt != null) { currentAwaitCatchFrame.HoistLocal(node.LocalOpt, F); } // store pending exception // as the first expression in a filter var sourceOpt = node.ExceptionSourceOpt; var rewrittenFilter = (BoundExpression)this.Visit(filterOpt); var newFilter = sourceOpt == null? F.Sequence( storePending, rewrittenFilter) : F.Sequence( storePending, AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame), rewrittenFilter); catchAndPend = node.Update( catchTemp, F.Local(catchTemp), catchType, exceptionFilterOpt: newFilter, body: F.Block( F.HiddenSequencePoint(), setPendingCatchNum)); } var handlerStatements = ArrayBuilder <BoundStatement> .GetInstance(); handlerStatements.Add(F.HiddenSequencePoint()); if (filterOpt == null) { var sourceOpt = node.ExceptionSourceOpt; if (sourceOpt != null) { BoundExpression assignSource = AssignCatchSource((BoundExpression)this.Visit(sourceOpt), currentAwaitCatchFrame); handlerStatements.Add(F.ExpressionStatement(assignSource)); } } handlerStatements.Add((BoundStatement)this.Visit(node.Body)); var handler = F.Block( handlerLocals, handlerStatements.ToImmutableAndFree() ); currentAwaitCatchFrame.handlers.Add(handler); return(catchAndPend); }