blob: e46af2cfaba0b6646c960e251ac93e6ee89252bb [file] [log] [blame]
// Copyright (c) 2019, 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.code;
public class IRMetadata {
private long first;
private long second;
public IRMetadata() {}
private IRMetadata(long first, long second) {
this.first = first;
this.second = second;
}
public static IRMetadata unknown() {
return new IRMetadata(0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL);
}
private boolean get(int bit) {
if (bit < 64) {
return isAnySetInFirst(1L << bit);
} else {
assert bit < 128;
int adjusted = bit - 64;
return isAnySetInSecond(1L << adjusted);
}
}
private boolean isAnySetInFirst(long mask) {
return (first & mask) != 0;
}
private boolean isAnySetInSecond(long mask) {
return (second & mask) != 0;
}
private void set(int bit) {
if (bit < 64) {
first |= (1L << bit);
} else {
assert bit < 128;
int adjusted = bit - 64;
second |= (1L << adjusted);
}
}
public void record(Instruction instruction) {
set(instruction.opcode());
}
public void merge(IRMetadata metadata) {
first |= metadata.first;
second |= metadata.second;
}
public boolean mayHaveAdd() {
return get(Opcodes.ADD);
}
public boolean mayHaveAnd() {
return get(Opcodes.AND);
}
public boolean mayHaveArrayLength() {
return get(Opcodes.ARRAY_LENGTH);
}
public boolean mayHaveCheckCast() {
return get(Opcodes.CHECK_CAST);
}
public boolean mayHaveConstNumber() {
return get(Opcodes.CONST_NUMBER);
}
public boolean mayHaveConstString() {
return get(Opcodes.CONST_STRING);
}
public boolean mayHaveDebugPosition() {
return get(Opcodes.DEBUG_POSITION);
}
public boolean mayHaveDexItemBasedConstString() {
return get(Opcodes.DEX_ITEM_BASED_CONST_STRING);
}
public boolean mayHaveDiv() {
return get(Opcodes.DIV);
}
public boolean mayHaveFieldGet() {
return mayHaveInstanceGet() || mayHaveStaticGet();
}
public boolean mayHaveFieldInstruction() {
assert Opcodes.INSTANCE_GET < 64;
assert Opcodes.INSTANCE_PUT < 64;
assert Opcodes.STATIC_GET < 64;
assert Opcodes.STATIC_PUT < 64;
long mask =
(1L << Opcodes.INSTANCE_GET)
| (1L << Opcodes.INSTANCE_PUT)
| (1L << Opcodes.STATIC_GET)
| (1L << Opcodes.STATIC_PUT);
boolean result = isAnySetInFirst(mask);
assert result
== (mayHaveInstanceGet()
|| mayHaveInstancePut()
|| mayHaveStaticGet()
|| mayHaveStaticPut());
return result;
}
public boolean mayHaveInitClass() {
return get(Opcodes.INIT_CLASS);
}
public boolean mayHaveInstanceGet() {
return get(Opcodes.INSTANCE_GET);
}
public boolean mayHaveInstancePut() {
return get(Opcodes.INSTANCE_PUT);
}
public boolean mayHaveInstanceOf() {
return get(Opcodes.INSTANCE_OF);
}
public boolean mayHaveIntSwitch() {
return get(Opcodes.INT_SWITCH);
}
public boolean mayHaveInvokeDirect() {
return get(Opcodes.INVOKE_DIRECT);
}
public boolean mayHaveInvokeInterface() {
return get(Opcodes.INVOKE_INTERFACE);
}
@SuppressWarnings("ConstantConditions")
public boolean mayHaveInvokeMethod() {
assert Opcodes.INVOKE_DIRECT < 64;
assert Opcodes.INVOKE_INTERFACE < 64;
assert Opcodes.INVOKE_POLYMORPHIC < 64;
assert Opcodes.INVOKE_STATIC < 64;
assert Opcodes.INVOKE_SUPER < 64;
assert Opcodes.INVOKE_VIRTUAL < 64;
long mask =
(1L << Opcodes.INVOKE_DIRECT)
| (1L << Opcodes.INVOKE_INTERFACE)
| (1L << Opcodes.INVOKE_POLYMORPHIC)
| (1L << Opcodes.INVOKE_STATIC)
| (1L << Opcodes.INVOKE_SUPER)
| (1L << Opcodes.INVOKE_VIRTUAL);
boolean result = isAnySetInFirst(mask);
assert result
== (mayHaveInvokeDirect()
|| mayHaveInvokeInterface()
|| mayHaveInvokePolymorphic()
|| mayHaveInvokeStatic()
|| mayHaveInvokeSuper()
|| mayHaveInvokeVirtual());
return result;
}
@SuppressWarnings("ConstantConditions")
public boolean mayHaveInvokeMethodWithReceiver() {
assert Opcodes.INVOKE_DIRECT < 64;
assert Opcodes.INVOKE_INTERFACE < 64;
assert Opcodes.INVOKE_SUPER < 64;
assert Opcodes.INVOKE_VIRTUAL < 64;
long mask =
(1L << Opcodes.INVOKE_DIRECT)
| (1L << Opcodes.INVOKE_INTERFACE)
| (1L << Opcodes.INVOKE_SUPER)
| (1L << Opcodes.INVOKE_VIRTUAL);
boolean result = isAnySetInFirst(mask);
assert result
== (mayHaveInvokeDirect()
|| mayHaveInvokeInterface()
|| mayHaveInvokeSuper()
|| mayHaveInvokeVirtual());
return result;
}
public boolean mayHaveInvokePolymorphic() {
return get(Opcodes.INVOKE_POLYMORPHIC);
}
public boolean mayHaveInvokeStatic() {
return get(Opcodes.INVOKE_STATIC);
}
public boolean mayHaveInvokeSuper() {
return get(Opcodes.INVOKE_SUPER);
}
public boolean mayHaveInvokeVirtual() {
return get(Opcodes.INVOKE_VIRTUAL);
}
public boolean mayHaveMonitorInstruction() {
return get(Opcodes.MONITOR);
}
public boolean mayHaveMul() {
return get(Opcodes.MUL);
}
public boolean mayHaveNewInstance() {
return get(Opcodes.NEW_INSTANCE);
}
public boolean mayHaveOr() {
return get(Opcodes.OR);
}
public boolean mayHaveRem() {
return get(Opcodes.REM);
}
public boolean mayHaveShl() {
return get(Opcodes.SHL);
}
public boolean mayHaveShr() {
return get(Opcodes.SHR);
}
public boolean mayHaveStaticGet() {
return get(Opcodes.STATIC_GET);
}
public boolean mayHaveStaticPut() {
return get(Opcodes.STATIC_PUT);
}
public boolean mayHaveStringSwitch() {
return get(Opcodes.STRING_SWITCH);
}
public boolean mayHaveSub() {
return get(Opcodes.SUB);
}
public boolean mayHaveUshr() {
return get(Opcodes.USHR);
}
public boolean mayHaveXor() {
return get(Opcodes.XOR);
}
public boolean mayHaveArithmeticOrLogicalBinop() {
// ArithmeticBinop
assert Opcodes.ADD < 64;
assert Opcodes.DIV < 64;
assert Opcodes.MUL < 64;
assert Opcodes.REM < 64;
assert Opcodes.SUB < 64;
// LogicalBinop
assert Opcodes.AND < 64;
assert Opcodes.OR < 64;
assert Opcodes.SHL < 64;
assert Opcodes.SHR < 64;
assert Opcodes.USHR >= 64;
assert Opcodes.XOR >= 64;
long mask =
(1L << Opcodes.ADD)
| (1L << Opcodes.DIV)
| (1L << Opcodes.MUL)
| (1L << Opcodes.REM)
| (1L << Opcodes.SUB)
| (1L << Opcodes.AND)
| (1L << Opcodes.OR)
| (1L << Opcodes.SHL)
| (1L << Opcodes.SHR)
| (1L << Opcodes.USHR)
| (1L << Opcodes.XOR);
long other = (1L << (Opcodes.USHR - 64)) | (1L << (Opcodes.XOR - 64));
boolean result = isAnySetInFirst(mask) || isAnySetInSecond(other);
assert result
== (mayHaveAdd()
|| mayHaveDiv()
|| mayHaveMul()
|| mayHaveRem()
|| mayHaveSub()
|| mayHaveAnd()
|| mayHaveOr()
|| mayHaveShl()
|| mayHaveShr()
|| mayHaveUshr()
|| mayHaveXor());
return result;
}
}