void AdjustJumpTargets(BasicBlock oldBlock, BasicBlock newBlock) { foreach (var origin in oldBlock.JumpOrigins) { if (newBlock == null) { throw CannotRemoveTarget; } if (origin.Exception != null) { AdjustException(origin.Exception); newBlock.AddJumpOrigin(origin); } else { newBlock.AddJumpOrigin(new JumpOrigin(newBlock, origin.OriginBlock, origin.Origin)); AdjustJump(origin); } } var oldInstruction = oldBlock.LastInstruction; Scanner.LogDebug(2, $"ADJUST JUMPS: {oldBlock} {newBlock} {oldInstruction}"); Scanner.Context.Debug(); foreach (var block in _block_list) { for (var j = 0; j < block.JumpOrigins.Count; j++) { var origin = block.JumpOrigins [j]; Scanner.LogDebug(2, $" ORIGIN: {origin}"); if (origin.Exception != null) { Scanner.LogDebug(2, $" EXCEPTION ORIGIN: {origin}"); if (origin.Exception.TryStart == oldInstruction) { throw CannotRemoveTarget; } if (origin.Exception.HandlerStart == oldInstruction) { throw CannotRemoveTarget; } } if (origin.Origin == oldInstruction) { throw CannotRemoveTarget; } if (origin.OriginBlock == oldBlock) { origin.OriginBlock = newBlock ?? throw CannotRemoveTarget; continue; } } } void AdjustException(ExceptionHandler handler) { if (handler.TryStart == oldBlock.FirstInstruction) { handler.TryStart = newBlock.FirstInstruction; } if (handler.TryEnd == oldBlock.FirstInstruction) { handler.TryEnd = newBlock.FirstInstruction; } if (handler.HandlerStart == oldBlock.FirstInstruction) { handler.HandlerStart = newBlock.FirstInstruction; } if (handler.HandlerEnd == oldBlock.FirstInstruction) { handler.HandlerEnd = newBlock.FirstInstruction; } if (handler.FilterStart == oldBlock.FirstInstruction) { handler.FilterStart = newBlock.FirstInstruction; } } void AdjustJump(JumpOrigin origin) { var instruction = origin.Origin; if (instruction.OpCode.OperandType == OperandType.InlineSwitch) { var labels = (Instruction [])instruction.Operand; for (int i = 0; i < labels.Length; i++) { if (labels [i] != oldBlock.FirstInstruction) { continue; } labels [i] = newBlock?.FirstInstruction ?? throw CannotRemoveTarget; } return; } if (instruction.OpCode.OperandType != OperandType.InlineBrTarget && instruction.OpCode.OperandType != OperandType.ShortInlineBrTarget) { throw DebugHelpers.AssertFailUnexpected(Method, origin.OriginBlock, instruction); } if (instruction.Operand != oldBlock.FirstInstruction) { throw DebugHelpers.AssertFailUnexpected(Method, origin.OriginBlock, instruction); } instruction.Operand = newBlock?.FirstInstruction ?? throw CannotRemoveTarget; } }
public void Dump(BasicBlock block) { Scanner.Context.LogMessage(MessageImportance.Low, $"{block}:"); Scanner.LogDebug(0, " ", null, block.JumpOrigins); Scanner.LogDebug(0, " ", null, block.Instructions); }
public bool TryGetBlock(Instruction instruction, out BasicBlock block) { return(_bb_by_instruction.TryGetValue(instruction, out block)); }
public int IndexOf(BasicBlock block) => _block_list.IndexOf(block);
internal void AddJumpOrigin(BasicBlock current, Instruction origin, Instruction target) { var block = _bb_by_instruction [target]; block.AddJumpOrigin(new JumpOrigin(block, current, origin)); }