コード例 #1
0
        public static void BuildAST(MethodDef method, CilBody body, ScopeBlock scope)
        {
            var builder     = new ILASTBuilder(method, body, scope);
            var basicBlocks = scope.GetBasicBlocks().Cast <CILBlock>().ToList();

            builder.BuildAST();
        }
コード例 #2
0
 private void SearchForHandlers(ScopeBlock scope, ExceptionHandler eh, ref IBasicBlock handler, ref IBasicBlock filter)
 {
     if (scope.ExceptionHandler == eh)
     {
         if (scope.Type == ScopeType.Handler)
         {
             handler = scope.GetBasicBlocks().First();
         }
         else if (scope.Type == ScopeType.Filter)
         {
             filter = scope.GetBasicBlocks().First();
         }
     }
     foreach (var child in scope.Children)
     {
         SearchForHandlers(child, eh, ref handler, ref filter);
     }
 }
コード例 #3
0
        private void AddTryStart(IRTransformer tr)
        {
            var tryStartInstrs = new List <IRInstruction>();

            for (int i = 0; i < this.thisScopes.Length; i++)
            {
                ScopeBlock scope = this.thisScopes[i];
                if (scope.Type != ScopeType.Try)
                {
                    continue;
                }
                if (scope.GetBasicBlocks().First() != tr.Block)
                {
                    continue;
                }

                // Search for handler/filter
                IBasicBlock handler = null, filter = null;
                this.SearchForHandlers(tr.RootScope, scope.ExceptionHandler, ref handler, ref filter);
                Debug.Assert(handler != null &&
                             (scope.ExceptionHandler.HandlerType != ExceptionHandlerType.Filter || filter != null));

                // Add instructions
                tryStartInstrs.Add(new IRInstruction(IROpCode.PUSH, new IRBlockTarget(handler)));

                IIROperand tryOperand = null;
                int        ehType;
                if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Catch)
                {
                    tryOperand = IRConstant.FromI4((int)tr.VM.Data.GetId(scope.ExceptionHandler.CatchType));
                    ehType     = tr.VM.Runtime.RTFlags.EH_CATCH;
                }
                else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Filter)
                {
                    tryOperand = new IRBlockTarget(filter);
                    ehType     = tr.VM.Runtime.RTFlags.EH_FILTER;
                }
                else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Fault)
                {
                    ehType = tr.VM.Runtime.RTFlags.EH_FAULT;
                }
                else if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Finally)
                {
                    ehType = tr.VM.Runtime.RTFlags.EH_FINALLY;
                }
                else
                {
                    throw new InvalidProgramException();
                }

                tryStartInstrs.Add(new IRInstruction(IROpCode.TRY, IRConstant.FromI4(ehType), tryOperand)
                {
                    Annotation = new EHInfo(scope.ExceptionHandler)
                });
            }
            tr.Instructions.InsertRange(0, tryStartInstrs);
        }
コード例 #4
0
        private ILASTBuilder(MethodDef method, CilBody body, ScopeBlock scope)
        {
            this.method = method;
            this.body   = body;
            this.scope  = scope;

            this.basicBlocks     = scope.GetBasicBlocks().Cast <CILBlock>().ToList();
            this.blockHeaders    = this.basicBlocks.ToDictionary(block => block.Content[0], block => block);
            this.blockStates     = new Dictionary <CILBlock, BlockState>();
            this.instrReferences = new List <ILASTExpression>();
            Debug.Assert(this.basicBlocks.Count > 0);
        }
コード例 #5
0
 public void Transform(IRTransformer tr)
 {
     this.thisScopes = tr.RootScope.SearchBlock(tr.Block);
     this.AddTryStart(tr);
     if (this.thisScopes[this.thisScopes.Length - 1].Type == ScopeType.Handler)
     {
         ScopeBlock   tryScope = this.SearchForTry(tr.RootScope, this.thisScopes[this.thisScopes.Length - 1].ExceptionHandler);
         ScopeBlock[] scopes   = tr.RootScope.SearchBlock(tryScope.GetBasicBlocks().First());
         this.thisScopes = scopes.TakeWhile(s => s != tryScope).ToArray();
     }
     tr.Instructions.VisitInstrs(this.VisitInstr, tr);
 }
コード例 #6
0
        public void AddMethod(MethodDef method, ScopeBlock rootScope)
        {
            ILBlock entry = null;

            foreach (ILBlock block in rootScope.GetBasicBlocks())
            {
                if (block.Id == 0)
                {
                    entry = block;
                }
                basicBlocks.Add(Tuple.Create(method, block));
            }
            Debug.Assert(entry != null);
            methodMap[method] = Tuple.Create(rootScope, entry);
        }
コード例 #7
0
        void ComputeBlockKeys(ScopeBlock rootScope)
        {
            var  blocks = rootScope.GetBasicBlocks().OfType <ILBlock>().ToList();
            uint id     = 1;

            Keys = blocks.ToDictionary(
                block => block,
                block => new BlockKey {
                Entry = id++, Exit = id++
            });
            var ehMap = MapEHs(rootScope);

            bool updated;

            do
            {
                updated = false;

                BlockKey key;

                key             = Keys[blocks[0]];
                key.Entry       = 0xfffffffe;
                Keys[blocks[0]] = key;

                key      = Keys[blocks[blocks.Count - 1]];
                key.Exit = 0xfffffffd;
                Keys[blocks[blocks.Count - 1]] = key;

                // Update the state ids with the maximum id
                foreach (var block in blocks)
                {
                    key = Keys[block];
                    if (block.Sources.Count > 0)
                    {
                        uint newEntry = block.Sources.Select(b => Keys[(ILBlock)b].Exit).Max();
                        if (key.Entry != newEntry)
                        {
                            key.Entry = newEntry;
                            updated   = true;
                        }
                    }
                    if (block.Targets.Count > 0)
                    {
                        uint newExit = block.Targets.Select(b => Keys[(ILBlock)b].Entry).Max();
                        if (key.Exit != newExit)
                        {
                            key.Exit = newExit;
                            updated  = true;
                        }
                    }
                    Keys[block] = key;
                }

                // Match finally enter = finally exit = try end exit
                // Match filter start = 0xffffffff
                MatchHandlers(ehMap, ref updated);
            } while (updated);

            // Replace id with actual values
            var idMap = new Dictionary <uint, uint>();

            idMap[0xffffffff] = 0;
            idMap[0xfffffffe] = methodInfo.EntryKey;
            idMap[0xfffffffd] = methodInfo.ExitKey;
            foreach (var block in blocks)
            {
                var key = Keys[block];

                uint entryId = key.Entry;
                if (!idMap.TryGetValue(entryId, out key.Entry))
                {
                    key.Entry = idMap[entryId] = (byte)runtime.Descriptor.Random.Next();
                }

                uint exitId = key.Exit;
                if (!idMap.TryGetValue(exitId, out key.Exit))
                {
                    key.Exit = idMap[exitId] = (byte)runtime.Descriptor.Random.Next();
                }

                Keys[block] = key;
            }
        }
コード例 #8
0
        void MapEHsInternal(ScopeBlock scope, EHMap map)
        {
            if (scope.Type == ScopeType.Filter)
            {
                map.Starts.Add((ILBlock)scope.GetBasicBlocks().First());
            }
            else if (scope.Type != ScopeType.None)
            {
                if (scope.ExceptionHandler.HandlerType == ExceptionHandlerType.Finally)
                {
                    FinallyInfo info;
                    if (!map.Finally.TryGetValue(scope.ExceptionHandler, out info))
                    {
                        map.Finally[scope.ExceptionHandler] = info = new FinallyInfo();
                    }

                    if (scope.Type == ScopeType.Try)
                    {
                        // Try End Next
                        var scopeBlocks = new HashSet <IBasicBlock>(scope.GetBasicBlocks());
                        foreach (ILBlock block in scopeBlocks)
                        {
                            if ((block.Flags & BlockFlags.ExitEHLeave) != 0 &&
                                (block.Targets.Count == 0 ||
                                 block.Targets.Any(target => !scopeBlocks.Contains(target))))
                            {
                                foreach (var target in block.Targets)
                                {
                                    info.TryEndNexts.Add((ILBlock)target);
                                }
                            }
                        }
                    }
                    else if (scope.Type == ScopeType.Handler)
                    {
                        // Finally End
                        IEnumerable <IBasicBlock> candidates;
                        if (scope.Children.Count > 0)
                        {
                            // Only ScopeType None can endfinally
                            candidates = scope.Children
                                         .Where(s => s.Type == ScopeType.None)
                                         .SelectMany(s => s.GetBasicBlocks());
                        }
                        else
                        {
                            candidates = scope.Content;
                        }
                        foreach (ILBlock block in candidates)
                        {
                            if ((block.Flags & BlockFlags.ExitEHReturn) != 0 &&
                                block.Targets.Count == 0)
                            {
                                info.FinallyEnds.Add(block);
                            }
                        }
                    }
                }
                if (scope.Type == ScopeType.Handler)
                {
                    map.Starts.Add((ILBlock)scope.GetBasicBlocks().First());
                }
            }
            foreach (var child in scope.Children)
            {
                MapEHsInternal(child, map);
            }
        }