| // 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.ir.code; | |
| import com.android.tools.r8.cf.LoadStoreHelper; | |
| import com.android.tools.r8.cf.code.CfStackInstruction; | |
| import com.android.tools.r8.cf.code.CfStackInstruction.Opcode; | |
| import com.android.tools.r8.errors.Unreachable; | |
| import com.android.tools.r8.graph.AppView; | |
| import com.android.tools.r8.graph.ProgramMethod; | |
| import com.android.tools.r8.ir.conversion.CfBuilder; | |
| import com.android.tools.r8.ir.conversion.DexBuilder; | |
| import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget; | |
| import com.android.tools.r8.ir.optimize.InliningConstraints; | |
| import com.android.tools.r8.lightir.LirBuilder; | |
| import com.google.common.collect.ImmutableList; | |
| public class Dup2 extends Instruction { | |
| public Dup2( | |
| StackValue destTowMinusThree, | |
| StackValue destTopMinusTwo, | |
| StackValue destTopMinusOne, | |
| StackValue destTop, | |
| Value srcBottom, | |
| Value srcTop) { | |
| this( | |
| new StackValues(destTowMinusThree, destTopMinusTwo, destTopMinusOne, destTop), | |
| srcBottom, | |
| srcTop); | |
| } | |
| private Dup2(StackValues dest, Value srcBottom, Value srcTop) { | |
| super(dest, ImmutableList.of(srcBottom, srcTop)); | |
| assert !srcBottom.getType().isWidePrimitive(); | |
| assert !srcTop.getType().isWidePrimitive(); | |
| assert dest.getStackValues().length == 4; | |
| assert srcBottom.isValueOnStack() && !(srcBottom instanceof StackValues); | |
| assert srcTop.isValueOnStack() && !(srcTop instanceof StackValues); | |
| } | |
| @Override | |
| public int opcode() { | |
| return Opcodes.DUP2; | |
| } | |
| @Override | |
| public <T> T accept(InstructionVisitor<T> visitor) { | |
| return visitor.visit(this); | |
| } | |
| @Override | |
| public Value setOutValue(Value newOutValue) { | |
| assert newOutValue instanceof StackValues; | |
| for (StackValue stackValue : ((StackValues) newOutValue).getStackValues()) { | |
| stackValue.definition = this; | |
| } | |
| return super.setOutValue(newOutValue); | |
| } | |
| private StackValue[] getStackValues() { | |
| return ((StackValues) outValue()).getStackValues(); | |
| } | |
| public StackValue outTopMinusThree() { | |
| return getStackValues()[0]; | |
| } | |
| public StackValue outTopMinusTwo() { | |
| return getStackValues()[1]; | |
| } | |
| public StackValue outTopMinusOne() { | |
| return getStackValues()[2]; | |
| } | |
| public StackValue outTop() { | |
| return getStackValues()[3]; | |
| } | |
| @Override | |
| public void buildDex(DexBuilder builder) { | |
| throw new Unreachable("This classfile-specific IR should not be inserted in the Dex backend."); | |
| } | |
| @Override | |
| public void buildLir(LirBuilder<Value, ?> builder) { | |
| throw new Unreachable("This classfile-specific IR should not be used before finalizing to CF."); | |
| } | |
| @Override | |
| public void buildCf(CfBuilder builder) { | |
| builder.add(new CfStackInstruction(Opcode.Dup2), this); | |
| } | |
| @Override | |
| public boolean identicalNonValueNonPositionParts(Instruction other) { | |
| return other.isDup2(); | |
| } | |
| @Override | |
| public int maxInValueRegister() { | |
| return 0; | |
| } | |
| @Override | |
| public int maxOutValueRegister() { | |
| throw new Unreachable(); | |
| } | |
| @Override | |
| public ConstraintWithTarget inliningConstraint( | |
| InliningConstraints inliningConstraints, ProgramMethod context) { | |
| return inliningConstraints.forDup2(); | |
| } | |
| @Override | |
| public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) { | |
| // Intentionally empty. Dup2 is a stack operation. | |
| } | |
| @Override | |
| public boolean hasInvariantOutType() { | |
| return false; | |
| } | |
| @Override | |
| public boolean isDup2() { | |
| return true; | |
| } | |
| @Override | |
| public Dup2 asDup2() { | |
| return this; | |
| } | |
| @Override | |
| public boolean instructionMayTriggerMethodInvocation(AppView<?> appView, ProgramMethod context) { | |
| return false; | |
| } | |
| } |