blob: 2785f5704741fbf14f703abe7b1192f1af7e2212 [file] [log] [blame]
// Copyright (c) 2018, 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.utils.codeinspector;
import com.android.tools.r8.dex.code.DexAget;
import com.android.tools.r8.dex.code.DexAgetBoolean;
import com.android.tools.r8.dex.code.DexAgetByte;
import com.android.tools.r8.dex.code.DexAgetChar;
import com.android.tools.r8.dex.code.DexAgetObject;
import com.android.tools.r8.dex.code.DexAgetShort;
import com.android.tools.r8.dex.code.DexAgetWide;
import com.android.tools.r8.dex.code.DexAput;
import com.android.tools.r8.dex.code.DexAputBoolean;
import com.android.tools.r8.dex.code.DexAputByte;
import com.android.tools.r8.dex.code.DexAputChar;
import com.android.tools.r8.dex.code.DexAputObject;
import com.android.tools.r8.dex.code.DexAputShort;
import com.android.tools.r8.dex.code.DexAputWide;
import com.android.tools.r8.dex.code.DexArrayLength;
import com.android.tools.r8.dex.code.DexCheckCast;
import com.android.tools.r8.dex.code.DexConst;
import com.android.tools.r8.dex.code.DexConst16;
import com.android.tools.r8.dex.code.DexConst4;
import com.android.tools.r8.dex.code.DexConstClass;
import com.android.tools.r8.dex.code.DexConstHigh16;
import com.android.tools.r8.dex.code.DexConstString;
import com.android.tools.r8.dex.code.DexConstStringJumbo;
import com.android.tools.r8.dex.code.DexConstWide;
import com.android.tools.r8.dex.code.DexConstWide16;
import com.android.tools.r8.dex.code.DexConstWide32;
import com.android.tools.r8.dex.code.DexConstWideHigh16;
import com.android.tools.r8.dex.code.DexGoto;
import com.android.tools.r8.dex.code.DexIfEq;
import com.android.tools.r8.dex.code.DexIfEqz;
import com.android.tools.r8.dex.code.DexIfGe;
import com.android.tools.r8.dex.code.DexIfGez;
import com.android.tools.r8.dex.code.DexIfGt;
import com.android.tools.r8.dex.code.DexIfGtz;
import com.android.tools.r8.dex.code.DexIfLe;
import com.android.tools.r8.dex.code.DexIfLez;
import com.android.tools.r8.dex.code.DexIfLt;
import com.android.tools.r8.dex.code.DexIfLtz;
import com.android.tools.r8.dex.code.DexIfNe;
import com.android.tools.r8.dex.code.DexIfNez;
import com.android.tools.r8.dex.code.DexIget;
import com.android.tools.r8.dex.code.DexIgetBoolean;
import com.android.tools.r8.dex.code.DexIgetByte;
import com.android.tools.r8.dex.code.DexIgetChar;
import com.android.tools.r8.dex.code.DexIgetObject;
import com.android.tools.r8.dex.code.DexIgetShort;
import com.android.tools.r8.dex.code.DexIgetWide;
import com.android.tools.r8.dex.code.DexInstanceOf;
import com.android.tools.r8.dex.code.DexInstruction;
import com.android.tools.r8.dex.code.DexInvokeCustom;
import com.android.tools.r8.dex.code.DexInvokeCustomRange;
import com.android.tools.r8.dex.code.DexInvokeDirect;
import com.android.tools.r8.dex.code.DexInvokeDirectRange;
import com.android.tools.r8.dex.code.DexInvokeInterface;
import com.android.tools.r8.dex.code.DexInvokeInterfaceRange;
import com.android.tools.r8.dex.code.DexInvokeStatic;
import com.android.tools.r8.dex.code.DexInvokeStaticRange;
import com.android.tools.r8.dex.code.DexInvokeSuper;
import com.android.tools.r8.dex.code.DexInvokeSuperRange;
import com.android.tools.r8.dex.code.DexInvokeVirtual;
import com.android.tools.r8.dex.code.DexInvokeVirtualRange;
import com.android.tools.r8.dex.code.DexIput;
import com.android.tools.r8.dex.code.DexIputBoolean;
import com.android.tools.r8.dex.code.DexIputByte;
import com.android.tools.r8.dex.code.DexIputChar;
import com.android.tools.r8.dex.code.DexIputObject;
import com.android.tools.r8.dex.code.DexIputShort;
import com.android.tools.r8.dex.code.DexIputWide;
import com.android.tools.r8.dex.code.DexMonitorEnter;
import com.android.tools.r8.dex.code.DexMonitorExit;
import com.android.tools.r8.dex.code.DexMulDouble;
import com.android.tools.r8.dex.code.DexMulDouble2Addr;
import com.android.tools.r8.dex.code.DexMulFloat;
import com.android.tools.r8.dex.code.DexMulFloat2Addr;
import com.android.tools.r8.dex.code.DexMulInt;
import com.android.tools.r8.dex.code.DexMulInt2Addr;
import com.android.tools.r8.dex.code.DexMulIntLit16;
import com.android.tools.r8.dex.code.DexMulIntLit8;
import com.android.tools.r8.dex.code.DexMulLong;
import com.android.tools.r8.dex.code.DexMulLong2Addr;
import com.android.tools.r8.dex.code.DexNewArray;
import com.android.tools.r8.dex.code.DexNewInstance;
import com.android.tools.r8.dex.code.DexNop;
import com.android.tools.r8.dex.code.DexPackedSwitch;
import com.android.tools.r8.dex.code.DexReturn;
import com.android.tools.r8.dex.code.DexReturnObject;
import com.android.tools.r8.dex.code.DexReturnVoid;
import com.android.tools.r8.dex.code.DexSget;
import com.android.tools.r8.dex.code.DexSgetBoolean;
import com.android.tools.r8.dex.code.DexSgetByte;
import com.android.tools.r8.dex.code.DexSgetChar;
import com.android.tools.r8.dex.code.DexSgetObject;
import com.android.tools.r8.dex.code.DexSgetShort;
import com.android.tools.r8.dex.code.DexSgetWide;
import com.android.tools.r8.dex.code.DexSparseSwitch;
import com.android.tools.r8.dex.code.DexSput;
import com.android.tools.r8.dex.code.DexSputBoolean;
import com.android.tools.r8.dex.code.DexSputByte;
import com.android.tools.r8.dex.code.DexSputChar;
import com.android.tools.r8.dex.code.DexSputObject;
import com.android.tools.r8.dex.code.DexSputShort;
import com.android.tools.r8.dex.code.DexSputWide;
import com.android.tools.r8.dex.code.DexThrow;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.code.SingleConstant;
import com.android.tools.r8.ir.code.WideConstant;
public class DexInstructionSubject implements InstructionSubject {
protected final DexInstruction instruction;
protected final MethodSubject method;
public DexInstructionSubject(DexInstruction instruction, MethodSubject method) {
this.instruction = instruction;
this.method = method;
}
@Override
public boolean isDexInstruction() {
return true;
}
@Override
public DexInstructionSubject asDexInstruction() {
return this;
}
@Override
public boolean isCfInstruction() {
return false;
}
@Override
public CfInstructionSubject asCfInstruction() {
return null;
}
@Override
public boolean isFieldAccess() {
return isInstanceGet() || isInstancePut() || isStaticGet() || isStaticPut();
}
@Override
public boolean isInstanceGet() {
return instruction instanceof DexIget
|| instruction instanceof DexIgetBoolean
|| instruction instanceof DexIgetByte
|| instruction instanceof DexIgetShort
|| instruction instanceof DexIgetChar
|| instruction instanceof DexIgetWide
|| instruction instanceof DexIgetObject;
}
@Override
public boolean isInstancePut() {
return instruction instanceof DexIput
|| instruction instanceof DexIputBoolean
|| instruction instanceof DexIputByte
|| instruction instanceof DexIputShort
|| instruction instanceof DexIputChar
|| instruction instanceof DexIputWide
|| instruction instanceof DexIputObject;
}
@Override
public boolean isStaticGet() {
return instruction instanceof DexSget
|| instruction instanceof DexSgetBoolean
|| instruction instanceof DexSgetByte
|| instruction instanceof DexSgetShort
|| instruction instanceof DexSgetChar
|| instruction instanceof DexSgetWide
|| instruction instanceof DexSgetObject;
}
@Override
public boolean isStaticPut() {
return instruction instanceof DexSput
|| instruction instanceof DexSputBoolean
|| instruction instanceof DexSputByte
|| instruction instanceof DexSputShort
|| instruction instanceof DexSputChar
|| instruction instanceof DexSputWide
|| instruction instanceof DexSputObject;
}
@Override
public DexField getField() {
assert isFieldAccess();
return instruction.getField();
}
@Override
public boolean isInvoke() {
return isInvokeVirtual()
|| isInvokeInterface()
|| isInvokeDirect()
|| isInvokeSuper()
|| isInvokeStatic();
}
@Override
public boolean isInvokeVirtual() {
return instruction instanceof DexInvokeVirtual || instruction instanceof DexInvokeVirtualRange;
}
@Override
public boolean isInvokeInterface() {
return instruction instanceof DexInvokeInterface
|| instruction instanceof DexInvokeInterfaceRange;
}
@Override
public boolean isInvokeStatic() {
return instruction instanceof DexInvokeStatic || instruction instanceof DexInvokeStaticRange;
}
@Override
public boolean isInvokeDynamic() {
return isInvokeCustom();
}
public boolean isInvokeCustom() {
return instruction instanceof DexInvokeCustom || instruction instanceof DexInvokeCustomRange;
}
public boolean isInvokeSuper() {
return instruction instanceof DexInvokeSuper || instruction instanceof DexInvokeSuperRange;
}
public boolean isInvokeDirect() {
return instruction instanceof DexInvokeDirect || instruction instanceof DexInvokeDirectRange;
}
@Override
public DexMethod getMethod() {
assert isInvoke();
return instruction.getMethod();
}
@Override
public boolean isNop() {
return instruction instanceof DexNop;
}
@Override
public boolean isConstNumber() {
return instruction instanceof DexConst
|| instruction instanceof DexConst4
|| instruction instanceof DexConst16
|| instruction instanceof DexConstHigh16
|| instruction instanceof DexConstWide
|| instruction instanceof DexConstWide16
|| instruction instanceof DexConstWide32
|| instruction instanceof DexConstWideHigh16;
}
@Override
public boolean isConstNumber(long value) {
return isConstNumber() && getConstNumber() == value;
}
@Override
public boolean isConstNull() {
return isConst4() && isConstNumber(0);
}
@Override
public boolean isConstString(JumboStringMode jumboStringMode) {
return instruction instanceof DexConstString
|| (jumboStringMode == JumboStringMode.ALLOW && instruction instanceof DexConstStringJumbo);
}
@Override
public boolean isConstString(String value, JumboStringMode jumboStringMode) {
return (instruction instanceof DexConstString
&& ((DexConstString) instruction).BBBB.toSourceString().equals(value))
|| (jumboStringMode == JumboStringMode.ALLOW
&& instruction instanceof DexConstStringJumbo
&& ((DexConstStringJumbo) instruction).BBBBBBBB.toSourceString().equals(value));
}
@Override
public boolean isJumboString() {
return instruction instanceof DexConstStringJumbo;
}
@Override public long getConstNumber() {
assert isConstNumber();
if (instruction instanceof SingleConstant) {
return ((SingleConstant) instruction).decodedValue();
}
assert instruction instanceof WideConstant;
return ((WideConstant) instruction).decodedValue();
}
@Override
public String getConstString() {
if (instruction instanceof DexConstString) {
return ((DexConstString) instruction).BBBB.toSourceString();
}
if (instruction instanceof DexConstStringJumbo) {
return ((DexConstStringJumbo) instruction).BBBBBBBB.toSourceString();
}
return null;
}
@Override
public boolean isConstClass() {
return instruction instanceof DexConstClass;
}
@Override
public boolean isConstClass(String type) {
return isConstClass() && ((DexConstClass) instruction).getType().toString().equals(type);
}
@Override
public boolean isGoto() {
return instruction instanceof DexGoto;
}
@Override
public boolean isIfNez() {
return instruction instanceof DexIfNez;
}
@Override
public boolean isIfEq() {
return instruction instanceof DexIfEq;
}
@Override
public boolean isIfEqz() {
return instruction instanceof DexIfEqz;
}
@Override
public boolean isIfNull() {
// Not in DEX.
return false;
}
@Override
public boolean isIfNonNull() {
// Not in DEX.
return false;
}
@Override
public boolean isReturn() {
return instruction instanceof DexReturn;
}
@Override
public boolean isReturnVoid() {
return instruction instanceof DexReturnVoid;
}
@Override
public boolean isReturnObject() {
return instruction instanceof DexReturnObject;
}
@Override
public boolean isThrow() {
return instruction instanceof DexThrow;
}
@Override
public boolean isNewInstance() {
return instruction instanceof DexNewInstance;
}
@Override
public boolean isNewInstance(String type) {
return isNewInstance() && ((DexNewInstance) instruction).getType().toString().equals(type);
}
@Override
public boolean isCheckCast() {
return instruction instanceof DexCheckCast;
}
@Override
public boolean isCheckCast(String type) {
return isCheckCast() && ((DexCheckCast) instruction).getType().toString().equals(type);
}
@Override
public boolean isInstanceOf() {
return instruction instanceof DexInstanceOf;
}
@Override
public boolean isInstanceOf(String type) {
return isInstanceOf() && ((DexInstanceOf) instruction).getType().toString().equals(type);
}
public boolean isConst4() {
return instruction instanceof DexConst4;
}
@Override
public boolean isIf() {
return instruction instanceof DexIfEq
|| instruction instanceof DexIfEqz
|| instruction instanceof DexIfGe
|| instruction instanceof DexIfGez
|| instruction instanceof DexIfGt
|| instruction instanceof DexIfGtz
|| instruction instanceof DexIfLe
|| instruction instanceof DexIfLez
|| instruction instanceof DexIfLt
|| instruction instanceof DexIfLtz
|| instruction instanceof DexIfNe
|| instruction instanceof DexIfNez;
}
@Override
public boolean isSwitch() {
return isPackedSwitch() || isSparseSwitch();
}
@Override
public boolean isPackedSwitch() {
return instruction instanceof DexPackedSwitch;
}
@Override
public boolean isSparseSwitch() {
return instruction instanceof DexSparseSwitch;
}
@Override
public boolean isMultiplication() {
return instruction instanceof DexMulInt
|| instruction instanceof DexMulIntLit8
|| instruction instanceof DexMulIntLit16
|| instruction instanceof DexMulInt2Addr
|| instruction instanceof DexMulFloat
|| instruction instanceof DexMulFloat2Addr
|| instruction instanceof DexMulLong
|| instruction instanceof DexMulLong2Addr
|| instruction instanceof DexMulDouble
|| instruction instanceof DexMulDouble2Addr;
}
@Override
public boolean isNewArray() {
return instruction instanceof DexNewArray;
}
@Override
public boolean isArrayLength() {
return instruction instanceof DexArrayLength;
}
@Override
public boolean isArrayGet() {
return instruction instanceof DexAget
|| instruction instanceof DexAgetBoolean
|| instruction instanceof DexAgetByte
|| instruction instanceof DexAgetChar
|| instruction instanceof DexAgetObject
|| instruction instanceof DexAgetShort
|| instruction instanceof DexAgetWide;
}
@Override
public boolean isArrayPut() {
return instruction instanceof DexAput
|| instruction instanceof DexAputBoolean
|| instruction instanceof DexAputByte
|| instruction instanceof DexAputChar
|| instruction instanceof DexAputObject
|| instruction instanceof DexAputShort
|| instruction instanceof DexAputWide;
}
@Override
public boolean isMonitorEnter() {
return instruction instanceof DexMonitorEnter;
}
@Override
public boolean isMonitorExit() {
return instruction instanceof DexMonitorExit;
}
@Override
public int size() {
return instruction.getSize();
}
@Override
public InstructionOffsetSubject getOffset(MethodSubject methodSubject) {
return new InstructionOffsetSubject(instruction.getOffset());
}
@Override
public MethodSubject getMethodSubject() {
return method;
}
@Override
public boolean equals(Object other) {
return other instanceof DexInstructionSubject
&& instruction.equals(((DexInstructionSubject) other).instruction);
}
@Override
public int hashCode() {
return instruction.hashCode();
}
@Override
public String toString() {
return instruction.toString();
}
public DexInstruction getInstruction() {
return instruction;
}
}