public bool canAppend(Block other) { if (other == null || other == this || getOnlyTarget() != other) { return(false); } // If it's eg. a leave, then don't merge them since it clears the stack. return(LastInstr.isBr() || Instr.isFallThrough(LastInstr.OpCode)); }
// Fix all branches so they now point to a Block, and not an Instruction. The // block's Targets field is updated, not the Instruction's Operand field. // Also update Block.FallThrough with next Block if last instr falls through. void fixBranchTargets(List <Block> instrToBlock, List <Block> allBlocks) { for (var i = 0; i < allBlocks.Count; i++) { var block = allBlocks[i]; var lastInstr = block.LastInstr; switch (lastInstr.OpCode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: var targetInstr = lastInstr.Operand as Instruction; if (targetInstr != null) { block.Targets = new List <Block> { instrToBlock[instrToIndex[targetInstr]] } } ; break; case OperandType.InlineSwitch: var switchTargets = (Instruction[])lastInstr.Operand; var newSwitchTargets = new List <Block>(); block.Targets = newSwitchTargets; foreach (var target in switchTargets) { if (target != null) { newSwitchTargets.Add(instrToBlock[instrToIndex[target]]); } } break; } if (i + 1 < allBlocks.Count && Instr.isFallThrough(lastInstr.OpCode)) { block.FallThrough = allBlocks[i + 1]; } } }