blob: db0d7cad635ffcb31cd7e26579aa9371b40fa678 [file] [log] [blame]
// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.framework.intraprocedural;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.TraversalUtils;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
public interface ControlFlowGraph<Block, Instruction> {
Block getEntryBlock();
default boolean hasUniquePredecessor(Block block) {
return TraversalUtils.isSingleton(counter -> traversePredecessors(block, counter));
}
default boolean hasUniqueSuccessor(Block block) {
return TraversalUtils.isSingleton(counter -> traverseSuccessors(block, counter));
}
default boolean hasUniqueSuccessorWithUniquePredecessor(Block block) {
return hasUniqueSuccessor(block) && hasUniquePredecessor(getUniqueSuccessor(block));
}
default Block getUniqueSuccessor(Block block) {
assert hasUniqueSuccessor(block);
return TraversalUtils.getFirst(collector -> traverseSuccessors(block, collector));
}
// Block traversal.
default <BT, CT> TraversalContinuation<BT, CT> traversePredecessors(
Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
return traversePredecessors(block, (predecessor, ignore) -> fn.apply(predecessor), null);
}
default <BT, CT> TraversalContinuation<BT, CT> traverseNormalPredecessors(
Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
return traverseNormalPredecessors(block, (predecessor, ignore) -> fn.apply(predecessor), null);
}
default <BT, CT> TraversalContinuation<BT, CT> traverseExceptionalPredecessors(
Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
return traverseExceptionalPredecessors(
block, (predecessor, ignore) -> fn.apply(predecessor), null);
}
default <BT, CT> TraversalContinuation<BT, CT> traverseSuccessors(
Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
return traverseSuccessors(block, (successor, ignore) -> fn.apply(successor), null);
}
default <BT, CT> TraversalContinuation<BT, CT> traverseNormalSuccessors(
Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
return traverseNormalSuccessors(block, (successor, ignore) -> fn.apply(successor), null);
}
default <BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
Block block, Function<? super Block, TraversalContinuation<BT, CT>> fn) {
return traverseExceptionalSuccessors(block, (successor, ignore) -> fn.apply(successor), null);
}
// Block traversal with result.
default <BT, CT> TraversalContinuation<BT, CT> traversePredecessors(
Block block,
BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue) {
return traverseNormalPredecessors(block, fn, initialValue)
.ifContinueThen(
continuation ->
traverseExceptionalPredecessors(block, fn, continuation.getValueOrDefault(null)));
}
<BT, CT> TraversalContinuation<BT, CT> traverseNormalPredecessors(
Block block,
BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue);
<BT, CT> TraversalContinuation<BT, CT> traverseExceptionalPredecessors(
Block block,
BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue);
default <BT, CT> TraversalContinuation<BT, CT> traverseSuccessors(
Block block,
BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue) {
return traverseNormalSuccessors(block, fn, initialValue)
.ifContinueThen(
continuation ->
traverseExceptionalSuccessors(block, fn, continuation.getValueOrDefault(null)));
}
<BT, CT> TraversalContinuation<BT, CT> traverseNormalSuccessors(
Block block,
BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue);
<BT, CT> TraversalContinuation<BT, CT> traverseExceptionalSuccessors(
Block block,
BiFunction<? super Block, ? super CT, TraversalContinuation<BT, CT>> fn,
CT initialValue);
// Block iteration.
default void forEachPredecessor(Block block, Consumer<Block> consumer) {
forEachNormalPredecessor(block, consumer);
forEachExceptionalPredecessor(block, consumer);
}
default void forEachNormalPredecessor(Block block, Consumer<Block> consumer) {
traverseNormalPredecessors(
block,
predecessor -> {
consumer.accept(predecessor);
return TraversalContinuation.doContinue();
});
}
default void forEachExceptionalPredecessor(Block block, Consumer<Block> consumer) {
traverseExceptionalPredecessors(
block,
exceptionalPredecessor -> {
consumer.accept(exceptionalPredecessor);
return TraversalContinuation.doContinue();
});
}
default void forEachSuccessor(Block block, Consumer<Block> consumer) {
forEachNormalSuccessor(block, consumer);
forEachExceptionalSuccessor(block, consumer);
}
default void forEachNormalSuccessor(Block block, Consumer<Block> consumer) {
traverseNormalSuccessors(
block,
successor -> {
consumer.accept(successor);
return TraversalContinuation.doContinue();
});
}
default void forEachExceptionalSuccessor(Block block, Consumer<Block> consumer) {
traverseExceptionalSuccessors(
block,
exceptionalSuccessor -> {
consumer.accept(exceptionalSuccessor);
return TraversalContinuation.doContinue();
});
}
// Instruction traversal.
<BT, CT> TraversalContinuation<BT, CT> traverseInstructions(
Block block, BiFunction<Instruction, CT, TraversalContinuation<BT, CT>> fn, CT initialValue);
}