Ejemplo n.º 1
0
            public override ScopeInfo OpenScope(
                ScopeType scopeType,
                Microsoft.Cci.ITypeReference exceptionType,
                ExceptionHandlerScope currentExceptionHandler
                )
            {
                Debug.Assert(
                    ((_handlers.Count == 0) && (scopeType == ScopeType.Try)) ||
                    (
                        (_handlers.Count > 0) &&
                        (
                            (scopeType == ScopeType.Catch) ||
                            (scopeType == ScopeType.Filter) ||
                            (scopeType == ScopeType.Finally) ||
                            (scopeType == ScopeType.Fault)
                        )
                    )
                    );

                Debug.Assert(currentExceptionHandler == _containingHandler);

                var handler = new ExceptionHandlerScope(this, scopeType, exceptionType);

                _handlers.Add(handler);
                return(handler);
            }
Ejemplo n.º 2
0
 public BasicBlockWithHandlerScope(
     ILBuilder builder,
     ExceptionHandlerScope enclosingHandler
     ) : base(builder)
 {
     this.enclosingHandler = enclosingHandler;
 }
Ejemplo n.º 3
0
        private bool ForwardLabelsAllowLeaving()
        {
            bool madeChanges = false;

            SmallDictionary <object, LabelInfo> .KeyCollection labels = _labelInfos.Keys;

            bool done;

            do
            {
                done = true;

                foreach (object label in labels)
                {
                    LabelInfo labelInfo = _labelInfos[label];
                    if (labelInfo.targetOfConditionalBranches)
                    {
                        // only unconditional labels can be forwarded as a leave
                        continue;
                    }

                    BasicBlock targetBlock = labelInfo.bb;

                    Debug.Assert(!IsSpecialEndHandlerBlock(targetBlock));

                    if (targetBlock.HasNoRegularInstructions)
                    {
                        BasicBlock targetsTarget = null;
                        switch (targetBlock.BranchCode)
                        {
                        case ILOpCode.Br:
                            targetsTarget = targetBlock.BranchBlock;
                            break;

                        case ILOpCode.Nop:
                            targetsTarget = targetBlock.NextBlock;
                            break;
                        }

                        if ((targetsTarget != null) && (targetsTarget != targetBlock))
                        {
                            ExceptionHandlerScope currentHandler = targetBlock.EnclosingHandler;
                            ExceptionHandlerScope newHandler     = targetsTarget.EnclosingHandler;

                            // can skip the jump if it is in the same try scope
                            if (CanMoveLabelToAnotherHandler(currentHandler, newHandler))
                            {
                                _labelInfos[label] = labelInfo.WithNewTarget(targetsTarget);
                                madeChanges        = true;

                                // since we modified at least one label we want to try again.
                                done = false;
                            }
                        }
                    }
                }
            } while (!done);

            return(madeChanges);
        }
Ejemplo n.º 4
0
 public ExceptionHandlerLeaderBlock(
     ILBuilder builder,
     ExceptionHandlerScope enclosingHandler,
     BlockType type
     ) : base(builder, enclosingHandler)
 {
     _type = type;
 }
Ejemplo n.º 5
0
            private static ScopeBounds GetBounds(ExceptionHandlerScope scope)
            {
                var scopes = ArrayBuilder <Cci.LocalScope> .GetInstance();

                var result = scope.GetLocalScopes(scopes, edgeInclusive: false);

                scopes.Free();
                return(result);
            }
            private static ScopeBounds GetBounds(ExceptionHandlerScope scope)
            {
                ArrayBuilder <Cci.LocalScope> scopes = ArrayBuilder <Cci.LocalScope> .GetInstance();

                ScopeBounds result = scope.GetLocalScopes(scopes);

                scopes.Free();
                return(result);
            }
            public virtual BasicBlock CreateBlock(ILBuilder builder)
            {
                ExceptionHandlerScope enclosingHandler = builder.EnclosingExceptionHandler;
                BasicBlock            block            = enclosingHandler == null?
                                                         AllocatePooledBlock(builder) :
                                                             new BasicBlockWithHandlerScope(builder, enclosingHandler);

                AddBlock(block);
                return(block);
            }
Ejemplo n.º 8
0
        private bool ForwardLabelsNoLeaving()
        {
            bool madeChanges = false;

            SmallDictionary <object, LabelInfo> .KeyCollection labels = _labelInfos.Keys;

            bool done;

            do
            {
                done = true;

                foreach (object label in labels)
                {
                    LabelInfo  labelInfo   = _labelInfos[label];
                    BasicBlock targetBlock = labelInfo.bb;

                    Debug.Assert(!IsSpecialEndHandlerBlock(targetBlock));

                    if (targetBlock.HasNoRegularInstructions)
                    {
                        BasicBlock targetsTarget = null;
                        switch (targetBlock.BranchCode)
                        {
                        case ILOpCode.Br:
                            targetsTarget = targetBlock.BranchBlock;
                            break;

                        case ILOpCode.Nop:
                            targetsTarget = targetBlock.NextBlock;
                            break;
                        }

                        if ((targetsTarget != null) && (targetsTarget != targetBlock))
                        {
                            ExceptionHandlerScope currentHandler = targetBlock.EnclosingHandler;
                            ExceptionHandlerScope newHandler     = targetsTarget.EnclosingHandler;

                            // forward the label if can be done without leaving current handler
                            if (currentHandler == newHandler)
                            {
                                _labelInfos[label] = labelInfo.WithNewTarget(targetsTarget);
                                madeChanges        = true;

                                // since we modified at least one label we want to try again.
                                done = false;
                            }
                        }
                    }
                }
            } while (!done);

            return(madeChanges);
        }
Ejemplo n.º 9
0
        // if branch is blocked by a nonterminating finally,
        // returns label for a landing block used as a target of blocked branches
        // Otherwise returns null
        private static object BlockedBranchDestination(BasicBlock src, BasicBlock dest)
        {
            ExceptionHandlerScope srcHandler = src.EnclosingHandler;

            // most common case - we are not in an exception handler.
            if (srcHandler == null)
            {
                return(null);
            }

            return(BlockedBranchDestinationSlow(dest.EnclosingHandler, srcHandler));
        }
Ejemplo n.º 10
0
            internal void CloseScope(ILBuilder builder)
            {
                ScopeInfo scope = _scopes.Pop();

                scope.CloseScope(builder);

                if (scope.IsExceptionHandler)
                {
                    _enclosingExceptionHandler = GetEnclosingExceptionHandler();
                }

                Debug.Assert(_enclosingExceptionHandler == GetEnclosingExceptionHandler());
            }
Ejemplo n.º 11
0
            internal void CloseScope(ILBuilder builder)
            {
                var scope = scopes.Pop();

                scope.CloseScope(builder);

                if (scope.IsExceptionHandler)
                {
                    this.enclosingExceptionHandler = GetEnclosingExceptionHandler();
                }

                Debug.Assert(this.enclosingExceptionHandler == GetEnclosingExceptionHandler());
            }
Ejemplo n.º 12
0
        private static bool CanMoveLabelToAnotherHandler(
            ExceptionHandlerScope currentHandler,
            ExceptionHandlerScope newHandler
            )
        {
            // Generally, assuming already valid code that contains "LABEL1: goto LABEL2"
            // we can substitute LABEL1 for LABEL2 so that the branches go directly to
            // the final destination.
            // Technically we can allow "moving" a label to any scope that contains the current one
            // However we should be careful with the cases when current label is protected by a
            // catch clause.
            //
            // [COMPAT]
            // If we move a label out of catch-protected try clause, we could be forcing JIT to inject
            // it back since, in the case of Thread.Abort, the re-throwing of the exception needs
            // to happen around this leave instruction which we would be removing.
            // In addition to just extra work on the JIT side, handling of this case appears to be
            // very delicate and there are known cases where JITs did not handle this particular
            // scenario correctly resulting in various violations of Thread.Abort behavior.
            // We cannot rely on these JIT issues being fixed in the end user environment.
            //
            // Considering that we are only winning a single LEAVE here, it seems reasonable to
            // just disallow labels to move outside of a catch-protected regions.

            // no handler means outermost scope (method level)
            if (newHandler == null && currentHandler.ContainingExceptionScope.FinallyOnly())
            {
                return(true);
            }

            // check if the target handler contains current handler.
            do
            {
                if (currentHandler == newHandler)
                {
                    return(true);
                }

                var containerScope = currentHandler.ContainingExceptionScope;
                if (!containerScope.FinallyOnly())
                {
                    // this may move the label outside of catch-protected region
                    // we will disallow that.
                    return(false);
                }

                currentHandler = containerScope.ContainingHandler;
            } while (currentHandler != null);

            return(false);
        }
Ejemplo n.º 13
0
            internal ScopeInfo OpenScope(ScopeType scopeType, Cci.ITypeReference exceptionType)
            {
                ScopeInfo scope = CurrentScope.OpenScope(scopeType, exceptionType, _enclosingExceptionHandler);

                _scopes.Push(scope);

                if (scope.IsExceptionHandler)
                {
                    _enclosingExceptionHandler = (ExceptionHandlerScope)scope;
                }

                Debug.Assert(_enclosingExceptionHandler == GetEnclosingExceptionHandler());
                return(scope);
            }
Ejemplo n.º 14
0
            public override ScopeInfo OpenScope(
                ScopeType scopeType,
                Cci.ITypeReference exceptionType,
                ExceptionHandlerScope currentExceptionHandler)
            {
                ScopeInfo scope = base.OpenScope(scopeType, exceptionType, currentExceptionHandler);

                if (_nestedScopes == null)
                {
                    _nestedScopes = ImmutableArray.CreateBuilder <ScopeInfo>(1);
                }
                _nestedScopes.Add(scope);
                return(scope);
            }
Ejemplo n.º 15
0
 public virtual ScopeInfo OpenScope(ScopeType scopeType,
                                    Microsoft.Cci.ITypeReference exceptionType,
                                    ExceptionHandlerScope currentHandler)
 {
     if (scopeType == ScopeType.TryCatchFinally)
     {
         return(new ExceptionHandlerContainerScope(currentHandler));
     }
     else
     {
         Debug.Assert(scopeType == ScopeType.Variable || scopeType == ScopeType.StateMachineVariable);
         return(new LocalScopeInfo());
     }
 }
Ejemplo n.º 16
0
            internal ScopeInfo OpenScope(ScopeType scopeType, Microsoft.Cci.ITypeReference exceptionType)
            {
                var scope = CurrentScope.OpenScope(scopeType, exceptionType, this.enclosingExceptionHandler);

                scopes.Push(scope);

                if (scope.IsExceptionHandler)
                {
                    this.enclosingExceptionHandler = (ExceptionHandlerScope)scope;
                }

                Debug.Assert(this.enclosingExceptionHandler == GetEnclosingExceptionHandler());
                return(scope);
            }
Ejemplo n.º 17
0
        /// <summary>
        /// Marks blocks that are recursively reachable from the given block.
        /// </summary>
        private static void MarkReachableFrom(ArrayBuilder <BasicBlock> reachableBlocks, BasicBlock block)
        {
tryAgain:

            if (block != null && block.Reachability == Reachability.NotReachable)
            {
                block.Reachability = Reachability.Reachable;

                ILOpCode branchCode = block.BranchCode;
                if (branchCode == ILOpCode.Nop && block.Type == BlockType.Normal)
                {
                    block = block.NextBlock;
                    goto tryAgain;
                }

                if (branchCode.CanFallThrough())
                {
                    PushReachableBlockToProcess(reachableBlocks, block.NextBlock);
                }
                else
                {
                    // If this block is an "endfinally" block, then clear
                    // the reachability of the following special block.
                    if (branchCode == ILOpCode.Endfinally)
                    {
                        ExceptionHandlerScope enclosingFinally = block.EnclosingHandler;
                        enclosingFinally?.UnblockFinally();
                    }
                }

                switch (block.Type)
                {
                case BlockType.Switch:
                    MarkReachableFromSwitch(reachableBlocks, block);
                    break;

                case BlockType.Try:
                    MarkReachableFromTry(reachableBlocks, block);
                    break;

                default:
                    MarkReachableFromBranch(reachableBlocks, block);
                    break;
                }
            }
        }
Ejemplo n.º 18
0
        private static object BlockedBranchDestinationSlow(
            ExceptionHandlerScope destHandler,
            ExceptionHandlerScope srcHandler
            )
        {
            ScopeInfo destHandlerScope = null;

            if (destHandler != null)
            {
                destHandlerScope = destHandler.ContainingExceptionScope;
            }

            // go from the source out until no longer crossing any finally blocks
            // between source and destination
            // if any finally blocks found in the process, check if they are blocking
            while (srcHandler != destHandler)
            {
                // branches within same ContainingExceptionScope do not go through finally.
                // only checking that source and destination are within the same handler would miss the case
                // of branching from catch into corresponding try.
                if (srcHandler.ContainingExceptionScope == destHandlerScope)
                {
                    break;
                }

                if (srcHandler.Type == ScopeType.Try)
                {
                    var handlerBlock = srcHandler.LeaderBlock.NextExceptionHandler;
                    if (handlerBlock.Type == BlockType.Finally)
                    {
                        var blockedDest = handlerBlock.EnclosingHandler.BlockedByFinallyDestination;
                        if (blockedDest != null)
                        {
                            return(blockedDest);
                        }
                    }
                }

                srcHandler = srcHandler.ContainingExceptionScope.ContainingHandler;
            }

            return(null);
        }
Ejemplo n.º 19
0
        private static bool InSameOrOuterHandler(ExceptionHandlerScope currentHandler,
                                                 ExceptionHandlerScope newHandler)
        {
            // no handler means outermost scope (method level)
            if (newHandler == null)
            {
                return(true);
            }

            // check if the target handler contains current handler.
            do
            {
                if (currentHandler == newHandler)
                {
                    return(true);
                }

                currentHandler = currentHandler.ContainingExceptionScope.ContainingHandler;
            } while (currentHandler != null);

            return(false);
        }
Ejemplo n.º 20
0
            public override void CloseScope(ILBuilder builder)
            {
                Debug.Assert(_handlers.Count > 1);

                // Fix up the NextExceptionHandler reference of each leader block.
                ExceptionHandlerScope       tryScope      = _handlers[0];
                ExceptionHandlerLeaderBlock previousBlock = tryScope.LeaderBlock;

                for (int i = 1; i < _handlers.Count; i++)
                {
                    ExceptionHandlerScope       handlerScope = _handlers[i];
                    ExceptionHandlerLeaderBlock nextBlock    = handlerScope.LeaderBlock;

                    previousBlock.NextExceptionHandler = nextBlock;
                    previousBlock = nextBlock;
                }

                // Generate label for try/catch "leave" target.
                builder.MarkLabel(_endLabel);

                // hide the following code, since it could be reached through the label above.
                builder.DefineHiddenSequencePoint();

                Debug.Assert(builder._currentBlock == builder._labelInfos[_endLabel].bb);

                if (_handlers[1].Type == ScopeType.Finally)
                {
                    // Generate "nop" branch to itself. If this block is unreachable
                    // (because the finally block does not complete), the "nop" will be
                    // replaced by Br_s. On the other hand, if this block is reachable,
                    // the "nop" will be skipped so any "leave" instructions jumping
                    // to this block will jump to the next instead.
                    builder.EmitBranch(ILOpCode.Nop, _endLabel);

                    _handlers[1].SetBlockedByFinallyDestination(_endLabel);
                }
            }
Ejemplo n.º 21
0
        private static bool InSameOrOuterHandler(ExceptionHandlerScope currentHandler, 
                                                 ExceptionHandlerScope newHandler)
        {
            // no handler means outermost scope (method level)
            if (newHandler == null)
            {
                return true;
            }

            // check if the target handler contains current handler.
            do
            {
                if (currentHandler == newHandler)
                {
                    return true;
                }

                currentHandler = currentHandler.ContainingExceptionScope.ContainingHandler;

            } while (currentHandler != null);
            
            return false;
        }
Ejemplo n.º 22
0
            internal override void GetExceptionHandlerRegions(ArrayBuilder <Cci.ExceptionHandlerRegion> regions)
            {
                Debug.Assert(_handlers.Count > 1);

                ExceptionHandlerScope tryScope  = null;
                ScopeBounds           tryBounds = new ScopeBounds();

                foreach (ExceptionHandlerScope handlerScope in _handlers)
                {
                    // Partition I, section 12.4.2.5:
                    // The ordering of the exception clauses in the Exception Handler Table is important. If handlers are nested,
                    // the most deeply nested try blocks shall come before the try blocks that enclose them.
                    //
                    // so we collect the inner regions first.
                    handlerScope.GetExceptionHandlerRegions(regions);

                    ScopeBounds handlerBounds = GetBounds(handlerScope);

                    if (tryScope == null)
                    {
                        // the first scope that we see should be Try.
                        Debug.Assert(handlerScope.Type == ScopeType.Try);

                        tryScope  = handlerScope;
                        tryBounds = handlerBounds;

                        Reachability reachability = tryScope.LeaderBlock.Reachability;
                        Debug.Assert((reachability == Reachability.Reachable) || (reachability == Reachability.NotReachable));

                        // All handler blocks should have same reachability.
                        Debug.Assert(_handlers.All(h => (h.LeaderBlock.Reachability == reachability)));

                        if (reachability != Reachability.Reachable)
                        {
                            return;
                        }
                    }
                    else
                    {
                        Cci.ExceptionHandlerRegion region;
                        switch (handlerScope.Type)
                        {
                        case ScopeType.Finally:
                            region = new Cci.ExceptionHandlerRegionFinally(tryBounds.Begin, tryBounds.End, handlerBounds.Begin, handlerBounds.End);
                            break;

                        case ScopeType.Fault:
                            region = new Cci.ExceptionHandlerRegionFault(tryBounds.Begin, tryBounds.End, handlerBounds.Begin, handlerBounds.End);
                            break;

                        case ScopeType.Catch:
                            region = new Cci.ExceptionHandlerRegionCatch(tryBounds.Begin, tryBounds.End, handlerBounds.Begin, handlerBounds.End, handlerScope.ExceptionType);
                            break;

                        case ScopeType.Filter:
                            region = new Cci.ExceptionHandlerRegionFilter(tryBounds.Begin, tryBounds.End, handlerScope.FilterHandlerStart, handlerBounds.End, handlerBounds.Begin);
                            break;

                        default:
                            throw ExceptionUtilities.UnexpectedValue(handlerScope.Type);
                        }

                        regions.Add(region);
                    }
                }
            }
Ejemplo n.º 23
0
 public ExceptionHandlerContainerScope(ExceptionHandlerScope containingHandler)
 {
     _handlers          = ImmutableArray.CreateBuilder <ExceptionHandlerScope>(2);
     _containingHandler = containingHandler;
     _endLabel          = new object();
 }
Ejemplo n.º 24
0
        private static object BlockedBranchDestinationSlow(ExceptionHandlerScope destHandler, ExceptionHandlerScope srcHandler)
        {
            ScopeInfo destHandlerScope = null;
            if (destHandler != null)
            {
                destHandlerScope = destHandler.ContainingExceptionScope;
            }

            // go from the source out until we no longer crossing any finallies 
            // between source and destination
            // if any finallies found in the process, check if they are blocking
            while (srcHandler != destHandler)
            {
                // branches within same ContainingExceptionScope do not go through finally.
                // only checking that source and destination are within the same handler would miss the case
                // of branching from catch into corresponding try.
                if (srcHandler.ContainingExceptionScope == destHandlerScope)
                {
                    break;
                }

                if (srcHandler.Type == ScopeType.Try)
                {
                    var handlerBlock = srcHandler.LeaderBlock.NextExceptionHandler;
                    if (handlerBlock.Type == BlockType.Finally)
                    {
                        var blockedDest = handlerBlock.EnclosingHandler.BlockedByFinallyDestination;
                        if (blockedDest != null)
                        {
                            return blockedDest;
                        }
                    }
                }

                srcHandler = srcHandler.ContainingExceptionScope.ContainingHandler;
            }

            return null;
        }
Ejemplo n.º 25
0
        private static bool CanMoveLabelToAnotherHandler(ExceptionHandlerScope currentHandler,
                                                 ExceptionHandlerScope newHandler)
        {
            // Generally, assuming already valid code that contains "LABEL1: goto LABEL2" 
            // we can substitute LABEL1 for LABEL2 so that the branches go directly to 
            // the final destination.
            // Technically we can allow "moving" a label to any scope that contains the current one
            // However we should be careful with the cases when current label is protected by a 
            // catch clause.
            // 
            // [COMPAT]
            // If we move a label out of catch-protected try clause, we could be forcing JIT to inject 
            // it back since, in the case of Thread.Abort, the re-throwing of the exception needs 
            // to happen around this leave instruction which we would be removing.
            // In addition to just extra work on the JIT side, handling of this case appears to be
            // very delicate and there are known cases where JITs did not handle this particular 
            // scenario correctly resulting in various violations of Thread.Abort behavior.
            // We cannot rely on these JIT issues being fixed in the end user environment.
            //
            // Considering that we are only winning a single LEAVE here, it seems reasonable to 
            // just disallow labels to move outside of a catch-protected regions.

            // no handler means outermost scope (method level)
            if (newHandler == null && currentHandler.ContainingExceptionScope.FinallyOnly())
            {
                return true;
            }

            // check if the target handler contains current handler.
            do
            {
                if (currentHandler == newHandler)
                {
                    return true;
                }

                var containerScope = currentHandler.ContainingExceptionScope;
                if (!containerScope.FinallyOnly())
                {
                    // this may move the label outside of catch-protected region
                    // we will disallow that.
                    return false;
                }

                currentHandler = containerScope.ContainingHandler;
            } while (currentHandler != null);

            return false;
        }
Ejemplo n.º 26
0
 public BasicBlockWithHandlerScope(ILBuilder builder, ExceptionHandlerScope enclosingHandler)
     : base(builder)
 {
     this.enclosingHandler = enclosingHandler;
 }
Ejemplo n.º 27
0
 public ExceptionHandlerLeaderBlock(ILBuilder builder, ExceptionHandlerScope enclosingHandler, BlockType type) :
     base(builder, enclosingHandler)
 {
     _type = type;
 }
Ejemplo n.º 28
0
 public SwitchBlock(ILBuilder builder, ExceptionHandlerScope enclosingHandler) :
     base(builder, enclosingHandler)
 {
     this.SetBranchCode(ILOpCode.Switch);
 }
Ejemplo n.º 29
0
 public SwitchBlock(ILBuilder builder, ExceptionHandlerScope enclosingHandler) :
     base(builder, enclosingHandler)
 {
     this.SetBranchCode(ILOpCode.Switch);
 }
 public ExceptionHandlerAttribute(Type ExceptionType, ExceptionHandlerScope Scope = ExceptionHandlerScope.Global)
 {
     this.Scope         = Scope;
     this.ExceptionType = ExceptionType;
 }