// Depth-first order void search(BaseBlock bb) { if (hasVisited(bb)) return; visited[bb] = true; var block = bb as Block; // Block or ScopeBlock if (block != null) { // Since the sorted array will be in reverse order, and we want the // conditional branches to fall through to their fall-through target, make // sure the FallThrough target is added last! Some conditional instructions // aren't reversible (eg. beq and bne.un) since they don't take the same // types of arguments. This will also make sure .NET Reflector doesn't // crash (sometimes). var targets = new List<Block>(block.getTargets()); targets.Reverse(); foreach (var target in targets) { var child = scopeBlock.toChild(target); if (child != null) search(child); } } sorted.Add(bb); }
void ScanBaseBlock(BaseBlock bb, int stackStart) { scanBaseBlockStack.Push(new ScanBaseBlockState(bb, stackStart)); while (scanBaseBlockStack.Count > 0) { var state = scanBaseBlockStack.Pop(); if (blockInfos.ContainsKey(state.bb) || !scopeBlock.IsOurBaseBlock(state.bb)) { continue; } var blockInfo = new BlockInfo(state.bb, state.stackStart); blockInfos[state.bb] = blockInfo; var block = state.bb as Block; if (block == null) // i.e., if try, filter, or handler block // It's not important to know the exact values, so we set them both to 0. // Compilers must make sure the stack is empty when entering a try block. { blockInfo.stackStart = blockInfo.stackEnd = 0; continue; } blockInfo.CalculateStackUsage(); foreach (var target in block.GetTargets()) { scanBaseBlockStack.Push(new ScanBaseBlockState(target, blockInfo.stackEnd)); } } }
// Add a block to be processed later, including all its enclosing ScopeBlocks. void addBaseBlock(BaseBlock baseBlock) { for (BaseBlock bb = baseBlock; bb != null; bb = bb.Parent) { baseBlocksToCheck.Push(bb); } }
void addToNewList(BaseBlock bb) { if (inNewList.ContainsKey(bb) || !scopeBlock.isOurBaseBlock(bb)) return; inNewList[bb] = false; var blockInfo = blockInfos[bb]; var block = bb as Block; if (blockInfo.stackStart == 0 || ReferenceEquals(bb, sorted[0]) || block == null || block.Sources == null || isInNewList(block.Sources)) { } else { foreach (var source in block.Sources) { if (!scopeBlock.isOurBaseBlock(source)) continue; int oldCount = newList.Count; addToNewList(source); // Make sure it's before this block if (oldCount != newList.Count) break; } } inNewList[bb] = true; newList.Add(bb); }
void doBaseBlock(BaseBlock bb) { BlockState current = stateStack.Peek(); ScopeBlock newOne = getScopeBlock(bb); if (newOne == null) return; // Not a BaseBlock somewhere inside this ScopeBlock if (newOne != current.scopeBlock) bb = newOne; bool hasVisited; if (!visited.TryGetValue(bb, out hasVisited)) visited[bb] = hasVisited = false; if (hasVisited) return; visited[bb] = true; if (bb is Block) doBlock(bb as Block); else if (bb is TryBlock) doTryBlock(bb as TryBlock); else if (bb is FilterHandlerBlock) doFilterHandlerBlock(bb as FilterHandlerBlock); else if (bb is HandlerBlock) doHandlerBlock(bb as HandlerBlock); else if (bb is TryHandlerBlock) { // The try handler block is usually after the try block, but sometimes it isn't... // Handle that case here. visited.Remove(bb); notProcessedYet.Add(bb); } else throw new ApplicationException("Invalid block found"); }
void AddToNewList(BaseBlock bb) { if (inNewList.ContainsKey(bb) || !scopeBlock.IsOurBaseBlock(bb)) { return; } inNewList[bb] = false; var blockInfo = blockInfos[bb]; var block = bb as Block; if (blockInfo.stackStart == 0 || ReferenceEquals(bb, sorted[0]) || block == null || block.Sources == null || IsInNewList(block.Sources)) { } else { foreach (var source in block.Sources) { if (!scopeBlock.IsOurBaseBlock(source)) { continue; } int oldCount = newList.Count; AddToNewList(source); // Make sure it's before this block if (oldCount != newList.Count) { break; } } } inNewList[bb] = true; newList.Add(bb); }
void processBaseBlock(BaseBlock baseBlock) { if (baseBlock == null || checkedBaseBlocks.ContainsKey(baseBlock)) { return; } checkedBaseBlocks[baseBlock] = true; if (baseBlock is Block) { var block = (Block)baseBlock; foreach (var block2 in block.getTargets()) { addBaseBlock(block2); } } else if (baseBlock is ScopeBlock) { var scopeBlock = (ScopeBlock)baseBlock; addScopeBlock(scopeBlock); if (scopeBlock.BaseBlocks != null && scopeBlock.BaseBlocks.Count > 0) { addBaseBlock(scopeBlock.BaseBlocks[0]); } } else { throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", baseBlock.GetType())); } }
bool hasVisited(BaseBlock bb) { bool hasVisited; if (visited.TryGetValue(bb, out hasVisited)) return hasVisited; visited[bb] = false; return false; }
public List <BaseBlock> Sort() { if (validBlocks.Count == 0) { return(new List <BaseBlock>()); } if (skipFirstBlock) { firstBlock = validBlocks[0]; } foreach (var block in validBlocks) { if (block != firstBlock) { blockToInfo[block] = new BlockInfo(block); } } sorted = new List <BaseBlock>(validBlocks.Count); var finalList = new List <BaseBlock>(validBlocks.Count); if (firstBlock is Block) { foreach (var target in GetTargets(firstBlock)) { Visit(target); finalList.AddRange(sorted); sorted.Clear(); } } foreach (var bb in validBlocks) { Visit(bb); finalList.AddRange(sorted); sorted.Clear(); } if (stack.Count > 0) { throw new ApplicationException("Stack isn't empty"); } if (firstBlock != null) { finalList.Insert(0, firstBlock); } else if (validBlocks[0] != finalList[0]) { // Make sure the original first block is first int index = finalList.IndexOf(validBlocks[0]); finalList.RemoveAt(index); finalList.Insert(0, validBlocks[0]); } return(finalList); }
// Returns the BaseBlock's ScopeBlock. The return value is either current ScopeBlock, // the ScopeBlock one step below current (current one's child), or null. ScopeBlock getScopeBlock(BaseBlock bb) { BlockState current = stateStack.Peek(); if (current.scopeBlock.isOurBaseBlock(bb)) { return(current.scopeBlock); } return((ScopeBlock)current.scopeBlock.toChild(bb)); }
BlockInfo GetInfo(BaseBlock baseBlock) { baseBlock = scopeBlock.ToChild(baseBlock); if (baseBlock == null) { return(null); } blockToInfo.TryGetValue(baseBlock, out var info); return(info); }
void doBaseBlock(BaseBlock bb) { BlockState current = stateStack.Peek(); ScopeBlock newOne = getScopeBlock(bb); if (newOne == null) { return; // Not a BaseBlock somewhere inside this ScopeBlock } if (newOne != current.scopeBlock) { bb = newOne; } bool hasVisited; if (!visited.TryGetValue(bb, out hasVisited)) { visited[bb] = hasVisited = false; } if (hasVisited) { return; } visited[bb] = true; if (bb is Block) { doBlock(bb as Block); } else if (bb is TryBlock) { doTryBlock(bb as TryBlock); } else if (bb is FilterHandlerBlock) { doFilterHandlerBlock(bb as FilterHandlerBlock); } else if (bb is HandlerBlock) { doHandlerBlock(bb as HandlerBlock); } else if (bb is TryHandlerBlock) { // The try handler block is usually after the try block, but sometimes it isn't... // Handle that case here. visited.Remove(bb); notProcessedYet.Add(bb); } else { throw new ApplicationException("Invalid block found"); } }
BlockInfo getInfo(BaseBlock baseBlock) { baseBlock = scopeBlock.toChild(baseBlock); if (baseBlock == null) { return(null); } BlockInfo info; blockToInfo.TryGetValue(baseBlock, out info); return(info); }
public void add(BaseBlock bb, int start, int end) { if (start < 0 || end < 0 || end < start) { throw new ApplicationException("Invalid start and/or end index"); } if (blocksLeft.Count != 0) { var bbi = blocksLeft[blocksLeft.Count - 1]; if (bbi.endInstr + 1 != start) { throw new ApplicationException("Previous BaseBlock does not end where this new one starts"); } } blocksLeft.Add(new BaseBlockInfo(start, end, bb)); }
// If bb is in baseBlocks (a direct child), return bb. If bb is a BaseBlock in a // ScopeBlock that is a direct child, then return that ScopeBlock. Else return null. public BaseBlock toChild(BaseBlock bb) { if (isOurBaseBlock(bb)) { return(bb); } for (var sb = bb.Parent; sb != null; sb = sb.Parent) { if (isOurBaseBlock(sb)) { return(sb); } } return(null); }
void Visit(BaseBlock bb) { var info = GetInfo(bb); if (info == null) { return; } if (info.baseBlock == firstBlock) { return; } if (info.Visited()) { return; } Visit(info); }
public List<BaseBlock> Sort() { if (validBlocks.Count == 0) return new List<BaseBlock>(); if (skipFirstBlock) firstBlock = validBlocks[0]; foreach (var block in validBlocks) { if (block != firstBlock) blockToInfo[block] = new BlockInfo(block); } sorted = new List<BaseBlock>(validBlocks.Count); var finalList = new List<BaseBlock>(validBlocks.Count); if (firstBlock is Block) { foreach (var target in GetTargets(firstBlock)) { Visit(target); finalList.AddRange(sorted); sorted.Clear(); } } foreach (var bb in validBlocks) { Visit(bb); finalList.AddRange(sorted); sorted.Clear(); } if (stack.Count > 0) throw new ApplicationException("Stack isn't empty"); if (firstBlock != null) finalList.Insert(0, firstBlock); else if (validBlocks[0] != finalList[0]) { // Make sure the original first block is first int index = finalList.IndexOf(validBlocks[0]); finalList.RemoveAt(index); finalList.Insert(0, validBlocks[0]); } return finalList; }
List <BaseBlock> GetTargets(BaseBlock baseBlock) { var list = new List <BaseBlock>(); if (baseBlock is Block block) { AddTargets(list, block.GetTargets()); } else if (baseBlock is TryBlock) { AddTargets(list, (TryBlock)baseBlock); } else if (baseBlock is TryHandlerBlock) { AddTargets(list, (TryHandlerBlock)baseBlock); } else { AddTargets(list, (ScopeBlock)baseBlock); } return(list); }
// Add a block to be processed later, including all its enclosing ScopeBlocks. void addBaseBlock(BaseBlock baseBlock) { for (BaseBlock bb = baseBlock; bb != null; bb = bb.Parent) baseBlocksToCheck.Push(bb); }
void doBaseBlock(BaseBlock bb) { BlockState current = stateStack.Peek(); ScopeBlock newOne = getScopeBlock(bb); if (newOne == null) return; // Not a BaseBlock somewhere inside this ScopeBlock if (newOne != current.scopeBlock) bb = newOne; bool hasVisited; if (!visited.TryGetValue(bb, out hasVisited)) visited[bb] = hasVisited = false; if (hasVisited) return; visited[bb] = true; if (bb is Block) doBlock(bb as Block); else if (bb is TryBlock) doTryBlock(bb as TryBlock); else if (bb is FilterHandlerBlock) doFilterHandlerBlock(bb as FilterHandlerBlock); else if (bb is HandlerBlock) doHandlerBlock(bb as HandlerBlock); else throw new ApplicationException("Invalid block found"); }
void Visit(BaseBlock bb) { var info = GetInfo(bb); if (info == null) return; if (info.baseBlock == firstBlock) return; if (info.Visited()) return; Visit(info); }
List<BaseBlock> GetTargets(BaseBlock baseBlock) { var list = new List<BaseBlock>(); if (baseBlock is Block) { var block = (Block)baseBlock; AddTargets(list, block.GetTargets()); } else if (baseBlock is TryBlock) AddTargets(list, (TryBlock)baseBlock); else if (baseBlock is TryHandlerBlock) AddTargets(list, (TryHandlerBlock)baseBlock); else AddTargets(list, (ScopeBlock)baseBlock); return list; }
BlockInfo GetInfo(BaseBlock baseBlock) { baseBlock = scopeBlock.ToChild(baseBlock); if (baseBlock == null) return null; BlockInfo info; blockToInfo.TryGetValue(baseBlock, out info); return info; }
public bool isOurBaseBlock(BaseBlock bb) { return(bb != null && bb.Parent == this); }
// Returns the BaseBlock's ScopeBlock. The return value is either current ScopeBlock, // the ScopeBlock one step below current (current one's child), or null. ScopeBlock getScopeBlock(BaseBlock bb) { BlockState current = stateStack.Peek(); if (current.scopeBlock.isOurBlockBase(bb)) return current.scopeBlock; return (ScopeBlock)current.scopeBlock.toChild(bb); }
public ScanBaseBlockState(BaseBlock bb, int stackStart) { this.bb = bb; this.stackStart = stackStart; }
public BaseBlockInfo(int start, int end, BaseBlock bb) { startInstr = start; endInstr = end; baseBlock = bb; }
public BlockInfo(BaseBlock baseBlock, int stackStart) { this.baseBlock = baseBlock; this.stackStart = stackStart; }
public BlockInfo(BaseBlock baseBlock) => this.baseBlock = baseBlock;
void scanBaseBlock(BaseBlock bb, int stackStart) { if (blockInfos.ContainsKey(bb) || !scopeBlock.isOurBaseBlock(bb)) return; var blockInfo = new BlockInfo(bb, stackStart); blockInfos[bb] = blockInfo; var block = bb as Block; if (block == null) { // i.e., if try, filter, or handler block // It's not important to know the exact values, so we set them both to 0. // Compilers must make sure the stack is empty when entering a try block. blockInfo.stackStart = blockInfo.stackEnd = 0; return; } blockInfo.calculateStackUsage(); foreach (var target in block.getTargets()) scanBaseBlock(target, blockInfo.stackEnd); }
// Returns the BaseBlock's ScopeBlock. The return value is either current ScopeBlock, // the ScopeBlock one step below current (current one's child), or null. ScopeBlock GetScopeBlock(BaseBlock bb) { BlockState current = stateStack.Peek(); if (current.scopeBlock.IsOurBaseBlock(bb)) return current.scopeBlock; return (ScopeBlock)current.scopeBlock.ToChild(bb); }
public List<BaseBlock> getBlocks(BaseBlock parent) { if (blocksLeft.Count == 0) return new List<BaseBlock>(); int startIndex, endIndex; var lb = getBlocks(0, blocksLeft[blocksLeft.Count - 1].endInstr, out startIndex, out endIndex); return updateParent(lb, parent); }
// Replace the BaseBlocks with a new BaseBlock, returning the old ones. public List<BaseBlock> replace(int startInstr, int endInstr, BaseBlock bb) { int startIndex, endIndex; var rv = getBlocks(startInstr, endInstr, out startIndex, out endIndex); updateParent(rv, bb); var bbi = new BaseBlockInfo(blocksLeft[startIndex].startInstr, blocksLeft[endIndex].endInstr, bb); blocksLeft.RemoveRange(startIndex, endIndex - startIndex + 1); blocksLeft.Insert(startIndex, bbi); return rv; }
void visit(BaseBlock bb) { var info = getInfo(bb); if (info == null) return; if (info.baseBlock == firstBlock) return; if (info.visited()) return; visit(info); }
void processBaseBlock(BaseBlock baseBlock) { if (baseBlock == null || checkedBaseBlocks.ContainsKey(baseBlock)) return; checkedBaseBlocks[baseBlock] = true; if (baseBlock is Block) { var block = (Block)baseBlock; foreach (var block2 in block.getTargets()) addBaseBlock(block2); } else if (baseBlock is ScopeBlock) { var scopeBlock = (ScopeBlock)baseBlock; addScopeBlock(scopeBlock); if (scopeBlock.BaseBlocks != null && scopeBlock.BaseBlocks.Count > 0) addBaseBlock(scopeBlock.BaseBlocks[0]); } else throw new ApplicationException(string.Format("Unknown BaseBlock type {0}", baseBlock.GetType())); }
public void Add(BaseBlock bb, int start, int end) { if (start < 0 || end < 0 || end < start) throw new ApplicationException("Invalid start and/or end index"); if (blocksLeft.Count != 0) { var bbi = blocksLeft[blocksLeft.Count - 1]; if (bbi.endInstr + 1 != start) throw new ApplicationException("Previous BaseBlock does not end where this new one starts"); } blocksLeft.Add(new BaseBlockInfo(start, end, bb)); }
public BlockInfo(BaseBlock baseBlock) { this.baseBlock = baseBlock; }
void ScanBaseBlock(BaseBlock bb, int stackStart) { scanBaseBlockStack.Push(new ScanBaseBlockState(bb, stackStart)); while (scanBaseBlockStack.Count > 0) { var state = scanBaseBlockStack.Pop(); if (blockInfos.ContainsKey(state.bb) || !scopeBlock.IsOurBaseBlock(state.bb)) continue; var blockInfo = new BlockInfo(state.bb, state.stackStart); blockInfos[state.bb] = blockInfo; var block = state.bb as Block; if (block == null) { // i.e., if try, filter, or handler block // It's not important to know the exact values, so we set them both to 0. // Compilers must make sure the stack is empty when entering a try block. blockInfo.stackStart = blockInfo.stackEnd = 0; continue; } blockInfo.CalculateStackUsage(); foreach (var target in block.GetTargets()) scanBaseBlockStack.Push(new ScanBaseBlockState(target, blockInfo.stackEnd)); } }
List<BaseBlock> updateParent(List<BaseBlock> lb, BaseBlock parent) { foreach (var bb in lb) bb.Parent = parent; return lb; }