ICollection <T> GetTargetInstructions(T i) { List <T> result = new List <T>(1); // if there are more multiple branches T[] targets = LinearInstructionAdapter <T> .GetOperand(i) as T[]; if (targets == null) { T target = LinearInstructionAdapter <T> .GetOperand(i) as T; if (target != null) { result.Add(target); return(result); } } else { foreach (T instr in targets) { result.Add(instr); } return(result); } return(result); }
bool IsBlockLeader(T i) { if (LinearInstructionAdapter <T> .GetPrevious(i) == null) { return(true); } // Check whether this was a start of an exception protected area if (exceptionHandlersStarts.Contains(i)) { return(true); } if (IsBlockTerminator(LinearInstructionAdapter <T> .GetPrevious(i))) { return(true); } // Check whether the instruction has label if (HasLabel(i)) { return(true); } return(false); }
void ComputeLabels(IEnumerable <T> instructions) { Debug.Assert(labels == null, "Labels must be null"); labels = new HashSet <T>(); foreach (T i in instructions) { switch (LinearInstructionAdapter <T> .GetFlowControl(i)) { case FlowControl.Cond_Branch: case FlowControl.Branch: var targets = GetTargetInstructions(i); foreach (T target in targets) { labels.Add(target); } break; } } }
bool IsBlockTerminator(T i) { // first instruction in the collection starts a block switch (LinearInstructionAdapter <T> .GetFlowControl(i)) { // Ensures leave and endfinally do not create new block in structure CFG case FlowControl.Branch: case FlowControl.Return: case FlowControl.Break: case FlowControl.Cond_Branch: case FlowControl.Throw: return(true); } T nextInstr = LinearInstructionAdapter <T> .GetNext(i); if (nextInstr != null) { return(HasLabel(nextInstr) || exceptionHandlersStarts.Contains(nextInstr)); } // The next inst is null which means the end of the body. return(true); }
void ConnectBlock(BasicBlock <T> block) { if (block.Last == null) { throw new ArgumentException("Undelimited node at " + block.Last); } T lastInst = block.Last; T nextInst = LinearInstructionAdapter <T> .GetNext(lastInst); var targets = GetTargetInstructions(lastInst); switch (LinearInstructionAdapter <T> .GetFlowControl(lastInst)) { // treat the call as next case FlowControl.Call: // intentional fall through case FlowControl.Next: // intentional fall through case FlowControl.Cond_Branch: { if (nextInst != null) // in the cases when it is last and there is no inst.Next // Add the next instruction as a target to the list of targets. { targets.Add(nextInst); } break; } case FlowControl.Return: // intentional fall through case FlowControl.Branch: // intentional fall through case FlowControl.Throw: // intentional fall through break; default: throw new NotSupportedException( string.Format("Unhandled instruction flow behavior {0}: {1}", LinearInstructionAdapter <T> .GetFlowControl(lastInst), lastInst.ToString(), lastInst.ToString())); } foreach (var target in targets) { Debug.Assert(target != null, "Target cannot be null!"); BasicBlock <T> successor = GetNodeContaining(target); // Check whether the successor already exists. Can happen when having branches pointing // to one and the same block. Eg. switch with no break. if (block.Successors.IndexOf(successor) < 0) { block.Successors.Add(successor); successor.Predecessors.Add(block); } } // Nothing to do, everything is already done, exit early. if (nextInst == null || targets.Contains(nextInst)) { return; } // We need to rule out the end of catch, because it ends with a branch and this would end up // duplicating the successors if (exceptionHandlersEnds.Contains(lastInst)) { BasicBlock <T> successor = GetNodeContaining(nextInst); block.Successors.Add(successor); successor.Predecessors.Add(block); } }