Skeleton for open/closed interfaces analysis on cf code
Change-Id: I39d08bb93352e3a82ef95b3e737a1d05d8e32995
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java
index 9156bc4..4cf9e5e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/framework/intraprocedural/cf/CfControlFlowGraph.java
@@ -57,6 +57,10 @@
return blocks.get(blockEntry);
}
+ public CfBlock getEntryBlock() {
+ return getBlock(code.getInstructions().get(0));
+ }
+
@Override
public <BT, CT> TraversalContinuation<BT, CT> traverseNormalPredecessors(
CfBlock block,
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/BottomCfFrameState.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/BottomCfFrameState.java
new file mode 100644
index 0000000..789881b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/BottomCfFrameState.java
@@ -0,0 +1,26 @@
+// 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.optimize.interfaces.analysis;
+
+public class BottomCfFrameState extends CfFrameState {
+
+ private static final BottomCfFrameState INSTANCE = new BottomCfFrameState();
+
+ private BottomCfFrameState() {}
+
+ static BottomCfFrameState getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return this == other;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java
new file mode 100644
index 0000000..ac4ce53
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfFrameState.java
@@ -0,0 +1,36 @@
+// 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.optimize.interfaces.analysis;
+
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractState;
+
+public abstract class CfFrameState extends AbstractState<CfFrameState> {
+
+ public static CfFrameState bottom() {
+ return BottomCfFrameState.getInstance();
+ }
+
+ public static ErroneousCfFrameState error() {
+ return ErroneousCfFrameState.getInstance();
+ }
+
+ @Override
+ public CfFrameState asAbstractState() {
+ return this;
+ }
+
+ @Override
+ public final CfFrameState join(CfFrameState state) {
+ // TODO(b/214496607): Implement join.
+ throw new Unimplemented();
+ }
+
+ @Override
+ public abstract boolean equals(Object other);
+
+ @Override
+ public abstract int hashCode();
+}
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
new file mode 100644
index 0000000..2e9b913
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
@@ -0,0 +1,77 @@
+// 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.optimize.interfaces.analysis;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.Code;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractTransferFunction;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.DataflowAnalysisResult;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.TransferFunctionResult;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.cf.CfBlock;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.cf.CfControlFlowGraph;
+import com.android.tools.r8.ir.analysis.framework.intraprocedural.cf.CfIntraproceduralDataflowAnalysis;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class CfOpenClosedInterfacesAnalysis {
+
+ private final AppView<AppInfoWithLiveness> appView;
+
+ public CfOpenClosedInterfacesAnalysis(AppView<AppInfoWithLiveness> appView) {
+ this.appView = appView;
+ }
+
+ public void run() {
+ // TODO(b/214496607): Parallelize the analysis.
+ for (DexProgramClass clazz : appView.appInfo().classes()) {
+ clazz.forEachProgramMethodMatching(DexEncodedMethod::hasCode, this::processMethod);
+ }
+ }
+
+ private void processMethod(ProgramMethod method) {
+ Code code = method.getDefinition().getCode();
+ if (!code.isCfCode()) {
+ assert code.isDefaultInstanceInitializerCode() || code.isThrowNullCode();
+ return;
+ }
+
+ CfCode cfCode = code.asCfCode();
+ CfControlFlowGraph cfg = CfControlFlowGraph.create(cfCode);
+ CfIntraproceduralDataflowAnalysis<CfFrameState> analysis =
+ new CfIntraproceduralDataflowAnalysis<>(
+ CfFrameState.bottom(), cfg, new TransferFunction(method));
+ DataflowAnalysisResult result = analysis.run(cfg.getEntryBlock());
+ // TODO(b/214496607): Determine open interfaces.
+ }
+
+ private class TransferFunction
+ implements AbstractTransferFunction<CfBlock, CfInstruction, CfFrameState> {
+
+ private final ProgramMethod context;
+
+ TransferFunction(ProgramMethod context) {
+ this.context = context;
+ }
+
+ @Override
+ public TransferFunctionResult<CfFrameState> apply(
+ CfInstruction instruction, CfFrameState state) {
+ // TODO(b/214496607): Implement this.
+ throw new Unimplemented();
+ }
+
+ @Override
+ public CfFrameState computeBlockEntryState(
+ CfBlock cfBlock, CfBlock predecessor, CfFrameState predecessorExitState) {
+ // TODO(b/214496607): Implement this.
+ throw new Unimplemented();
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java
new file mode 100644
index 0000000..a077574
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ConcreteCfFrameState.java
@@ -0,0 +1,44 @@
+// 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.optimize.interfaces.analysis;
+
+import com.android.tools.r8.cf.code.CfFrame.FrameType;
+import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectSortedMap;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Objects;
+
+public class ConcreteCfFrameState extends CfFrameState {
+
+ private final Int2ObjectSortedMap<FrameType> locals;
+ private final Deque<FrameType> stack;
+
+ ConcreteCfFrameState() {
+ this(new Int2ObjectAVLTreeMap<>(), new ArrayDeque<>());
+ }
+
+ ConcreteCfFrameState(Int2ObjectSortedMap<FrameType> locals, Deque<FrameType> stack) {
+ this.locals = locals;
+ this.stack = stack;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ConcreteCfFrameState that = (ConcreteCfFrameState) o;
+ return locals.equals(that.locals) && stack.equals(that.stack);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(locals, stack);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ErroneousCfFrameState.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ErroneousCfFrameState.java
new file mode 100644
index 0000000..687cd3b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/ErroneousCfFrameState.java
@@ -0,0 +1,27 @@
+// 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.optimize.interfaces.analysis;
+
+/** An analysis state representing that the code does not type check. */
+public class ErroneousCfFrameState extends CfFrameState {
+
+ private static final ErroneousCfFrameState INSTANCE = new ErroneousCfFrameState();
+
+ private ErroneousCfFrameState() {}
+
+ static ErroneousCfFrameState getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return this == other;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+}