private int repeatInternal( @NotNull PseudocodeImpl originalPseudocode, @Nullable Label startLabel, @Nullable Label finishLabel, int labelCount) { Integer startIndex = startLabel != null ? ((PseudocodeLabel) startLabel).getTargetInstructionIndex() : Integer.valueOf(0); assert startIndex != null; Integer finishIndex = finishLabel != null ? ((PseudocodeLabel) finishLabel).getTargetInstructionIndex() : Integer.valueOf(originalPseudocode.mutableInstructionList.size()); assert finishIndex != null; Map<Label, Label> originalToCopy = Maps.newLinkedHashMap(); Multimap<Instruction, Label> originalLabelsForInstruction = HashMultimap.create(); for (PseudocodeLabel label : originalPseudocode.labels) { Integer index = label.getTargetInstructionIndex(); if (index == null) continue; // label is not bounded yet if (label == startLabel || label == finishLabel) continue; if (startIndex <= index && index <= finishIndex) { originalToCopy.put(label, label.copy(labelCount++)); originalLabelsForInstruction.put(getJumpTarget(label), label); } } for (Label label : originalToCopy.values()) { labels.add((PseudocodeLabel) label); } for (int index = startIndex; index < finishIndex; index++) { Instruction originalInstruction = originalPseudocode.mutableInstructionList.get(index); repeatLabelsBindingForInstruction( originalInstruction, originalToCopy, originalLabelsForInstruction); Instruction copy = copyInstruction(originalInstruction, originalToCopy); addInstruction(copy); if (originalInstruction == originalPseudocode.errorInstruction && copy instanceof SubroutineExitInstruction) { errorInstruction = (SubroutineExitInstruction) copy; } if (originalInstruction == originalPseudocode.exitInstruction && copy instanceof SubroutineExitInstruction) { exitInstruction = (SubroutineExitInstruction) copy; } if (originalInstruction == originalPseudocode.sinkInstruction && copy instanceof SubroutineSinkInstruction) { sinkInstruction = (SubroutineSinkInstruction) copy; } } if (finishIndex < mutableInstructionList.size()) { repeatLabelsBindingForInstruction( originalPseudocode.mutableInstructionList.get(finishIndex), originalToCopy, originalLabelsForInstruction); } return labelCount; }
private static Instruction copyInstruction( @NotNull Instruction instruction, @NotNull Map<Label, Label> originalToCopy) { if (instruction instanceof AbstractJumpInstruction) { Label originalTarget = ((AbstractJumpInstruction) instruction).getTargetLabel(); if (originalToCopy.containsKey(originalTarget)) { return ((AbstractJumpInstruction) instruction).copy(originalToCopy.get(originalTarget)); } } if (instruction instanceof NondeterministicJumpInstruction) { List<Label> originalTargets = ((NondeterministicJumpInstruction) instruction).getTargetLabels(); List<Label> copyTargets = copyLabels(originalTargets, originalToCopy); return ((NondeterministicJumpInstruction) instruction).copy(copyTargets); } return ((InstructionImpl) instruction).copy(); }
private void repeatLabelsBindingForInstruction( @NotNull Instruction originalInstruction, @NotNull Map<Label, Label> originalToCopy, @NotNull Multimap<Instruction, Label> originalLabelsForInstruction) { for (Label originalLabel : originalLabelsForInstruction.get(originalInstruction)) { bindLabel(originalToCopy.get(originalLabel)); } }
@NotNull private static List<Label> copyLabels( Collection<Label> labels, Map<Label, Label> originalToCopy) { List<Label> newLabels = Lists.newArrayList(); for (Label label : labels) { Label newLabel = originalToCopy.get(label); newLabels.add(newLabel != null ? newLabel : label); } return newLabels; }
/*package*/ void addInstruction(Instruction instruction) { mutableInstructionList.add(instruction); instruction.setOwner(this); if (instruction instanceof KtElementInstruction) { KtElementInstruction elementInstruction = (KtElementInstruction) instruction; representativeInstructions.put(elementInstruction.getElement(), instruction); } if (instruction instanceof MergeInstruction) { addMergedValues((MergeInstruction) instruction); } for (PseudoValue inputValue : instruction.getInputValues()) { addValueUsage(inputValue, instruction); for (PseudoValue mergedValue : getMergedValues(inputValue)) { addValueUsage(mergedValue, instruction); } } if (PseudocodeUtilsKt.calcSideEffectFree(instruction)) { sideEffectFree.add(instruction); } }