blob: e5d2489ad308870d563fa417a4c332a5f4e9fe78 [file] [log] [blame]
// Copyright (c) 2016, 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.code;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.function.BiPredicate;
public abstract class Format35c<T extends IndexedDexItem & StructuralItem<T>> extends Base3Format {
public final byte A;
public final byte C;
public final byte D;
public final byte E;
public final byte F;
public final byte G;
public T BBBB;
private static <T extends IndexedDexItem & StructuralItem<T>> void specify(
StructuralSpecification<Format35c<T>, ?> spec) {
spec.withInt(i -> i.A)
.withInt(i -> i.C)
.withInt(i -> i.D)
.withInt(i -> i.E)
.withInt(i -> i.F)
.withInt(i -> i.G)
.withItem(i -> i.BBBB);
}
// A | G | op | BBBB | F | E | D | C
Format35c(int high, BytecodeStream stream, T[] map) {
super(stream);
G = (byte) (high & 0xf);
A = (byte) ((high >> 4) & 0xf);
BBBB = map[read16BitValue(stream)];
int next = read8BitValue(stream);
E = (byte) (next & 0xf);
F = (byte) ((next >> 4) & 0xf);
next = read8BitValue(stream);
C = (byte) (next & 0xf);
D = (byte) ((next >> 4) & 0xf);
}
Format35c(int A, T BBBB, int C, int D, int E, int F, int G) {
assert 0 <= A && A <= Constants.U4BIT_MAX;
assert 0 <= C && C <= Constants.U4BIT_MAX;
assert 0 <= D && D <= Constants.U4BIT_MAX;
assert 0 <= E && E <= Constants.U4BIT_MAX;
assert 0 <= F && F <= Constants.U4BIT_MAX;
assert 0 <= G && G <= Constants.U4BIT_MAX;
this.A = (byte) A;
this.BBBB = BBBB;
this.C = (byte) C;
this.D = (byte) D;
this.E = (byte) E;
this.F = (byte) F;
this.G = (byte) G;
}
@Override
public final int hashCode() {
return ((BBBB.hashCode() << 24) | (A << 20) | (C << 16) | (D << 12) | (E << 8) | (F << 4)
| G) ^ getClass().hashCode();
}
@SuppressWarnings("unchecked")
@Override
final int internalAcceptCompareTo(Instruction other, CompareToVisitor visitor) {
return visitor.visit(this, (Format35c<T>) other, Format35c::specify);
}
private void appendRegisterArguments(StringBuilder builder, String separator) {
builder.append("{ ");
int[] values = new int[]{C, D, E, F, G};
for (int i = 0; i < A; i++) {
if (i != 0) {
builder.append(separator);
}
builder.append("v").append(values[i]);
}
builder.append(" }");
}
@Override
public String toString(ClassNameMapper naming) {
StringBuilder builder = new StringBuilder();
appendRegisterArguments(builder, " ");
builder.append(" ");
if (naming == null) {
builder.append(BBBB.toSmaliString());
} else {
builder.append(naming.originalNameOf(BBBB));
}
return formatString(builder.toString());
}
@Override
public String toSmaliString(ClassNameMapper naming) {
StringBuilder builder = new StringBuilder();
appendRegisterArguments(builder, ", ");
builder.append(", ");
// TODO(sgjesse): Add support for smali name mapping.
builder.append(BBBB.toSmaliString());
return formatSmaliString(builder.toString());
}
@Override
public boolean equals(Instruction other, BiPredicate<IndexedDexItem, IndexedDexItem> equality) {
if (other == null || (this.getClass() != other.getClass())) {
return false;
}
Format35c o = (Format35c) other;
return o.A == A && o.C == C && o.D == D && o.E == E && o.F == F && o.G == G
&& equality.test(BBBB, o.BBBB);
}
}