public static FlowGraph Create(MethodIL il) { HashSet <int> bbStarts = GetBasicBlockStarts(il); List <BasicBlock> bbs = new List <BasicBlock>(); void AddBB(int start, int count) { if (count > 0) { bbs.Add(new BasicBlock(start, count)); } } int prevStart = 0; foreach (int ofs in bbStarts.OrderBy(o => o)) { AddBB(prevStart, ofs - prevStart); prevStart = ofs; } AddBB(prevStart, il.GetILBytes().Length - prevStart); FlowGraph fg = new FlowGraph(bbs); // We know where each basic block starts now. Proceed by linking them together. ILReader reader = new ILReader(il.GetILBytes()); foreach (BasicBlock bb in bbs) { reader.Seek(bb.Start); while (reader.HasNext) { Debug.Assert(fg.Lookup(reader.Offset) == bb); ILOpcode opc = reader.ReadILOpcode(); if (opc.IsBranch()) { int tar = reader.ReadBranchDestination(opc); bb.Targets.Add(fg.Lookup(tar)); if (!opc.IsUnconditionalBranch()) { bb.Targets.Add(fg.Lookup(reader.Offset)); } break; } if (opc == ILOpcode.switch_) { uint numCases = reader.ReadILUInt32(); int jmpBase = reader.Offset + checked ((int)(numCases * 4)); bb.Targets.Add(fg.Lookup(jmpBase)); for (uint i = 0; i < numCases; i++) { int caseOfs = jmpBase + (int)reader.ReadILUInt32(); bb.Targets.Add(fg.Lookup(caseOfs)); } break; } if (opc == ILOpcode.ret || opc == ILOpcode.endfinally || opc == ILOpcode.endfilter || opc == ILOpcode.throw_ || opc == ILOpcode.rethrow) { break; } reader.Skip(opc); // Check fall through if (reader.HasNext) { BasicBlock nextBB = fg.Lookup(reader.Offset); if (nextBB != bb) { // Falling through bb.Targets.Add(nextBB); break; } } } } foreach (BasicBlock bb in bbs) { foreach (BasicBlock tar in bb.Targets) { tar.Sources.Add(bb); } } return(fg); }