private bool IsTransfer(RtlInstructionCluster i, RtlInstruction r) { return r is RtlGoto || r is RtlCall; }
/// <summary> /// Branches need to terminate the current basic block and make links /// to the 'true' and 'false' destinations. /// </summary> /// <param name="b"></param> /// <returns></returns> public bool VisitBranch(RtlBranch b) { // We don't know the 'then' block yet, as the following statements may chop up the block // we're presently in. Back-patch in when the block target is obtained. var branch = new Branch(b.Condition, new Block(blockCur.Procedure, "TMP!")); Emit(branch, blockCur); // The following statements may chop up the blockCur, so hang on to the essentials. var proc = blockCur.Procedure; RtlInstructionCluster ricDelayed = null; if ((b.Class & RtlClass.Delay) != 0) { rtlStream.MoveNext(); ricDelayed = rtlStream.Current; ric = ricDelayed; } var fallthruAddress = ric.Address + ric.Length; Block blockThen; if (!program.SegmentMap.IsValidAddress((Address)b.Target)) { blockThen = proc.AddBlock(this.ric.Address.GenerateName("l", "_then")); var jmpSite = state.OnBeforeCall(stackReg, arch.PointerType.Size); GenerateCallToOutsideProcedure(jmpSite, (Address)b.Target); Emit(new ReturnInstruction()); blockCur.Procedure.ControlGraph.AddEdge(blockCur, blockCur.Procedure.ExitBlock); } else { blockThen = BlockFromAddress(ric.Address, (Address)b.Target, proc, state.Clone()); } var blockElse = FallthroughBlock(ric.Address, proc, fallthruAddress); var branchingBlock = blockCur.IsSynthesized ? blockCur : scanner.FindContainingBlock(ric.Address); if ((b.Class & RtlClass.Delay) != 0 && ricDelayed.Instructions.Length > 0) { // Introduce stubs for the delay slot, but only // if the delay slot isn't empty. if ((b.Class & RtlClass.Annul) != 0) { EnsureEdge(proc, branchingBlock, blockElse); } else { Block blockDsF = null; blockDsF = proc.AddBlock(branchingBlock.Name + "_ds_f"); blockDsF.IsSynthesized = true; blockCur = blockDsF; ProcessRtlCluster(ricDelayed); EnsureEdge(proc, blockDsF, blockElse); EnsureEdge(proc, branchingBlock, blockDsF); } Block blockDsT = proc.AddBlock(branchingBlock.Name + "_ds_t"); blockDsT.IsSynthesized = true; blockCur = blockDsT; ProcessRtlCluster(ricDelayed); EnsureEdge(proc, blockDsT, blockThen); branch.Target = blockDsT; EnsureEdge(proc, branchingBlock, blockDsT); } else { branch.Target = blockThen; // The back-patch referred to above. EnsureEdge(proc, branchingBlock, blockElse); if (blockElse != blockThen) { EnsureEdge(proc, branchingBlock, blockThen); } else { proc.ControlGraph.AddEdge(branchingBlock, blockThen); } } if (BlockHasBeenScanned(blockElse)) { return(false); } else { blockCur = blockElse; return(true); } }
public CodePatch(RtlInstructionCluster cluster) { this.Code = cluster; }
/// <summary> /// Branches need to terminate the current basic block and make links /// to the 'true' and 'false' destinations. /// </summary> /// <param name="b"></param> /// <returns></returns> public bool VisitBranch(RtlBranch b) { // We don't know the 'then' block yet, as the following statements may chop up the block // we're presently in. Back-patch in when the block target is obtained. var branch = new Branch(b.Condition, new Block(blockCur.Procedure, "TMP!")); // The following statements may chop up the blockCur, so hang on to the essentials. var proc = blockCur.Procedure; RtlInstructionCluster ricDelayed = null; if ((b.Class & RtlClass.Delay) != 0) { rtlStream.MoveNext(); ricDelayed = rtlStream.Current; ric = ricDelayed; } var fallthruAddress = ric.Address + ric.Length; var blockThen = BlockFromAddress(ric.Address, b.Target, proc, state.Clone()); var blockElse = FallthroughBlock(ric.Address, proc, fallthruAddress); var branchingBlock = scanner.FindContainingBlock(ric.Address); Emit(branch, branchingBlock); if ((b.Class & RtlClass.Delay) != 0 && ricDelayed.Instructions.Count > 0) { // Introduce stubs for the delay slot, but only // if the delay slot isn't empty. if ((b.Class & RtlClass.Annul) != 0) { EnsureEdge(proc, branchingBlock, blockElse); } else { Block blockDsF = null; blockDsF = proc.AddBlock(branchingBlock.Name + "_ds_f"); blockDsF.IsSynthesized = true; blockCur = blockDsF; ProcessRtlCluster(ricDelayed); EnsureEdge(proc, blockDsF, blockElse); EnsureEdge(proc, branchingBlock, blockDsF); } Block blockDsT = proc.AddBlock(branchingBlock.Name + "_ds_t"); blockDsT.IsSynthesized = true; blockCur = blockDsT; ProcessRtlCluster(ricDelayed); EnsureEdge(proc, blockDsT, blockThen); branch.Target = blockDsT; EnsureEdge(proc, branchingBlock, blockDsT); } else { branch.Target = blockThen; // The back-patch referred to above. EnsureEdge(proc, branchingBlock, blockElse); EnsureEdge(proc, branchingBlock, blockThen); } // Now, switch to the fallthru block and keep rewriting. blockCur = blockElse; return(!blockElse.IsSynthesized); }
private bool IsTransfer(RtlInstructionCluster i, RtlInstruction r) { return(r is RtlGoto || r is RtlCall); }