public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (node.ExceptionFilterOpt == null) { return(base.VisitCatchBlock(node)); } BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt); BoundExpression rewrittenFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt); BoundBlock rewrittenBody = (BoundBlock)this.Visit(node.Body); TypeSymbol rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt); // EnC: We need to insert a hidden sequence point to handle function remapping in case // the containing method is edited while methods invoked in the condition are being executed. if (rewrittenFilter != null && !node.WasCompilerGenerated && this.Instrument) { rewrittenFilter = _instrumenter.InstrumentCatchClauseFilter(node, rewrittenFilter, _factory); } return(node.Update( node.Locals, rewrittenExceptionSourceOpt, rewrittenExceptionTypeOpt, rewrittenFilter, rewrittenBody, node.IsSynthesizedAsyncCatchAll)); }
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)); }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (node.ExceptionFilterOpt == null) { return(base.VisitCatchBlock(node)); } BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt); BoundExpression rewrittenFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt); BoundBlock rewrittenBody = (BoundBlock)this.Visit(node.Body); TypeSymbol rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt); // EnC: We need to insert a hidden sequence point to handle function remapping in case // the containing method is edited while methods invoked in the condition are being executed. return(node.Update( node.LocalOpt, rewrittenExceptionSourceOpt, rewrittenExceptionTypeOpt, AddConditionSequencePoint(rewrittenFilter, node), rewrittenBody, node.IsSynthesizedAsyncCatchAll)); }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (node.ExceptionFilterOpt == null) { return base.VisitCatchBlock(node); } BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt); BoundExpression rewrittenFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt); BoundBlock rewrittenBody = (BoundBlock)this.Visit(node.Body); TypeSymbol rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt); // EnC: We need to insert a hidden sequence point to handle function remapping in case // the containing method is edited while methods invoked in the condition are being executed. return node.Update( node.LocalOpt, rewrittenExceptionSourceOpt, rewrittenExceptionTypeOpt, AddConditionSequencePoint(rewrittenFilter, node), rewrittenBody, node.IsSynthesizedAsyncCatchAll); }
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); }
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; }
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 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); }
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)); }
public override BoundNode VisitCatchBlock(BoundCatchBlock node) { if (node.ExceptionFilterOpt == null) { return base.VisitCatchBlock(node); } BoundExpression rewrittenExceptionSourceOpt = (BoundExpression)this.Visit(node.ExceptionSourceOpt); BoundExpression rewrittenFilter = (BoundExpression)this.Visit(node.ExceptionFilterOpt); BoundBlock rewrittenBody = (BoundBlock)this.Visit(node.Body); TypeSymbol rewrittenExceptionTypeOpt = this.VisitType(node.ExceptionTypeOpt); // EnC: We need to insert a hidden sequence point to handle function remapping in case // the containing method is edited while methods invoked in the condition are being executed. if (rewrittenFilter != null && !node.WasCompilerGenerated && this.Instrument) { rewrittenFilter = _instrumenter.InstrumentCatchClauseFilter(node, rewrittenFilter, _factory); } return node.Update( node.Locals, rewrittenExceptionSourceOpt, rewrittenExceptionTypeOpt, rewrittenFilter, rewrittenBody, node.IsSynthesizedAsyncCatchAll); }