| // 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.cf.code; |
| |
| |
| import com.android.tools.r8.cf.CfPrinter; |
| import com.android.tools.r8.errors.Unreachable; |
| import com.android.tools.r8.graph.AppView; |
| import com.android.tools.r8.graph.CfCompareHelper; |
| import com.android.tools.r8.graph.DexField; |
| import com.android.tools.r8.graph.DexItemFactory; |
| import com.android.tools.r8.graph.GraphLens; |
| import com.android.tools.r8.graph.InitClassLens; |
| import com.android.tools.r8.graph.ProgramMethod; |
| import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils; |
| import com.android.tools.r8.naming.NamingLens; |
| import com.android.tools.r8.utils.structural.CompareToVisitor; |
| import com.android.tools.r8.utils.structural.HashingVisitor; |
| import com.android.tools.r8.utils.structural.StructuralSpecification; |
| import org.objectweb.asm.MethodVisitor; |
| import org.objectweb.asm.Opcodes; |
| |
| public abstract class CfFieldInstruction extends CfInstruction { |
| |
| private final DexField field; |
| private final DexField declaringField; |
| |
| private static void specify(StructuralSpecification<CfFieldInstruction, ?> spec) { |
| spec.withInt(CfFieldInstruction::getOpcode) |
| .withItem(CfFieldInstruction::getField) |
| .withItem(CfFieldInstruction::getDeclaringField); |
| } |
| |
| public CfFieldInstruction(DexField field) { |
| this(field, field); |
| } |
| |
| public CfFieldInstruction(DexField field, DexField declaringField) { |
| this.field = field; |
| this.declaringField = declaringField; |
| assert field.type == declaringField.type; |
| } |
| |
| public static CfFieldInstruction create(int opcode, DexField field, DexField declaringField) { |
| switch (opcode) { |
| case Opcodes.GETSTATIC: |
| return new CfStaticFieldRead(field, declaringField); |
| case Opcodes.PUTSTATIC: |
| return new CfStaticFieldWrite(field, declaringField); |
| case Opcodes.GETFIELD: |
| return new CfInstanceFieldRead(field, declaringField); |
| case Opcodes.PUTFIELD: |
| return new CfInstanceFieldWrite(field, declaringField); |
| default: |
| throw new Unreachable("Unexpected opcode " + opcode); |
| } |
| } |
| |
| public DexField getField() { |
| return field; |
| } |
| |
| public DexField getDeclaringField() { |
| return declaringField; |
| } |
| |
| public abstract int getOpcode(); |
| |
| @Override |
| public int getCompareToId() { |
| return getOpcode(); |
| } |
| |
| @Override |
| public int internalAcceptCompareTo( |
| CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) { |
| return visitor.visit(this, other.asFieldInstruction(), CfFieldInstruction::specify); |
| } |
| |
| @Override |
| public void internalAcceptHashing(HashingVisitor visitor) { |
| visitor.visit(this, CfFieldInstruction::specify); |
| } |
| |
| public abstract CfFieldInstruction createWithField(DexField field); |
| |
| @Override |
| public CfFieldInstruction asFieldInstruction() { |
| return this; |
| } |
| |
| @Override |
| public boolean isFieldInstruction() { |
| return true; |
| } |
| |
| @Override |
| public void write( |
| AppView<?> appView, |
| ProgramMethod context, |
| DexItemFactory dexItemFactory, |
| GraphLens graphLens, |
| InitClassLens initClassLens, |
| NamingLens namingLens, |
| LensCodeRewriterUtils rewriter, |
| MethodVisitor visitor) { |
| DexField rewrittenField = graphLens.lookupField(field); |
| DexField rewrittenDeclaringField = graphLens.lookupField(declaringField); |
| String owner = namingLens.lookupInternalName(rewrittenField.holder); |
| String name = namingLens.lookupName(rewrittenDeclaringField).toString(); |
| String desc = namingLens.lookupDescriptor(rewrittenField.type).toString(); |
| visitor.visitFieldInsn(getOpcode(), owner, name, desc); |
| } |
| |
| @Override |
| public int bytecodeSizeUpperBound() { |
| return 3; |
| } |
| |
| @Override |
| public void print(CfPrinter printer) { |
| printer.print(this); |
| } |
| |
| @Override |
| public boolean canThrow() { |
| return true; |
| } |
| } |