Exemple #1
0
 private void BuildPhiNodes()
 {
     foreach (KeyValuePair <CILBlock, BlockState> statePair in this.blockStates)
     {
         CILBlock   block = statePair.Key;
         BlockState state = statePair.Value;
         // source count = 0 => eh handlers begin state, having ex object
         if (block.Sources.Count == 0 && state.BeginStack.Length > 0)
         {
             Debug.Assert(state.BeginStack.Length == 1);
             var phi = new ILASTPhi
             {
                 Variable        = state.BeginStack[0],
                 SourceVariables = new[] { state.BeginStack[0] }
             };
             state.ASTTree.Insert(0, phi);
         }
         else if (state.BeginStack.Length > 0)
         {
             for (int varIndex = 0; varIndex < state.BeginStack.Length; varIndex++)
             {
                 var phi = new ILASTPhi {
                     Variable = state.BeginStack[varIndex]
                 };
                 phi.SourceVariables = new ILASTVariable[block.Sources.Count];
                 for (int i = 0; i < phi.SourceVariables.Length; i++)
                 {
                     phi.SourceVariables[i] = this.blockStates[block.Sources[i]].ASTTree.StackRemains[varIndex];
                 }
                 // reverse phi nodes => pop in correct order
                 state.ASTTree.Insert(0, phi);
             }
         }
     }
 }
Exemple #2
0
        private void BuildASTInternal()
        {
            var workList = new Stack <CILBlock>();

            this.PopulateBeginStates(workList);

            var visited = new HashSet <CILBlock>();

            while (workList.Count > 0)
            {
                CILBlock block = workList.Pop();
                if (visited.Contains(block))
                {
                    continue;
                }
                visited.Add(block);

                Debug.Assert(this.blockStates.ContainsKey(block));
                BlockState state = this.blockStates[block];
                Debug.Assert(state.ASTTree == null);

                ILASTTree       tree    = this.BuildAST(block.Content, state.BeginStack);
                ILASTVariable[] remains = tree.StackRemains;
                state.ASTTree           = tree;
                this.blockStates[block] = state;

                // Propagate stack states
                foreach (CILBlock successor in block.Targets)
                {
                    if (!this.blockStates.TryGetValue(successor, out BlockState successorState))
                    {
                        var blockVars = new ILASTVariable[remains.Length];
                        for (int i = 0; i < blockVars.Length; i++)
                        {
                            blockVars[i] = new ILASTVariable
                            {
                                Name         = string.Format("ph_{0:x2}_{1:x2}", successor.Id, i),
                                Type         = remains[i].Type,
                                VariableType = ILASTVariableType.PhiVar
                            }
                        }
                        ;
                        successorState = new BlockState
                        {
                            BeginStack = blockVars
                        };
                        this.blockStates[successor] = successorState;
                    }
                    else
                    {
                        if (successorState.BeginStack.Length != remains.Length)
                        {
                            throw new InvalidProgramException("Inconsistent stack depth.");
                        }
                    }
                    workList.Push(successor);
                }
            }
        }
Exemple #3
0
        private void PopulateBeginStates(Stack <CILBlock> workList)
        {
            for (int i = 0; i < this.body.ExceptionHandlers.Count; i++)
            {
                ExceptionHandler eh = this.body.ExceptionHandlers[i];
                this.blockStates[this.blockHeaders[eh.TryStart]] = new BlockState
                {
                    BeginStack = new ILASTVariable[0]
                };

                CILBlock handlerBlock = this.blockHeaders[eh.HandlerStart];
                workList.Push(handlerBlock);
                if (eh.HandlerType == ExceptionHandlerType.Fault ||
                    eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    this.blockStates[handlerBlock] = new BlockState
                    {
                        BeginStack = new ILASTVariable[0]
                    };
                }
                else
                {
                    var type = TypeInference.ToASTType(eh.CatchType.ToTypeSig());
                    // Do not process overlapped handler blocks twice
                    if (!this.blockStates.ContainsKey(handlerBlock))
                    {
                        var exVar = new ILASTVariable
                        {
                            Name         = string.Format("ex_{0:x2}", i),
                            Type         = type,
                            VariableType = ILASTVariableType.ExceptionVar,
                            Annotation   = eh
                        };
                        this.blockStates[handlerBlock] = new BlockState
                        {
                            BeginStack = new[] { exVar }
                        };
                    }
                    else
                    {
                        Debug.Assert(this.blockStates[handlerBlock].BeginStack.Length == 1);
                    }

                    if (eh.FilterStart != null)
                    {
                        var filterVar = new ILASTVariable
                        {
                            Name         = string.Format("ef_{0:x2}", i),
                            Type         = type,
                            VariableType = ILASTVariableType.FilterVar,
                            Annotation   = eh
                        };
                        CILBlock filterBlock = this.blockHeaders[eh.FilterStart];
                        workList.Push(filterBlock);
                        this.blockStates[filterBlock] = new BlockState
                        {
                            BeginStack = new[] { filterVar }
                        };
                    }
                }
            }
            this.blockStates[this.basicBlocks[0]] = new BlockState
            {
                BeginStack = new ILASTVariable[0]
            };
            workList.Push(this.basicBlocks[0]);
            foreach (CILBlock block in this.basicBlocks)
            {
                if (block.Sources.Count > 0)
                {
                    continue;
                }
                if (workList.Contains(block))
                {
                    continue;
                }
                this.blockStates[block] = new BlockState
                {
                    BeginStack = new ILASTVariable[0]
                };
                workList.Push(block);
            }
        }