1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dexgen.rop.code; 18 19 import com.android.dexgen.rop.cst.Constant; 20 import com.android.dexgen.rop.type.StdTypeList; 21 import com.android.dexgen.rop.type.Type; 22 import com.android.dexgen.rop.type.TypeBearer; 23 import com.android.dexgen.rop.type.TypeList; 24 25 /** 26 * Plain instruction, which has no embedded data and which cannot possibly 27 * throw an exception. 28 */ 29 public final class PlainInsn 30 extends Insn { 31 /** 32 * Constructs an instance. 33 * 34 * @param opcode {@code non-null;} the opcode 35 * @param position {@code non-null;} source position 36 * @param result {@code null-ok;} spec for the result, if any 37 * @param sources {@code non-null;} specs for all the sources 38 */ 39 public PlainInsn(Rop opcode, SourcePosition position, 40 RegisterSpec result, RegisterSpecList sources) { 41 super(opcode, position, result, sources); 42 43 switch (opcode.getBranchingness()) { 44 case Rop.BRANCH_SWITCH: 45 case Rop.BRANCH_THROW: { 46 throw new IllegalArgumentException("bogus branchingness"); 47 } 48 } 49 50 if (result != null && opcode.getBranchingness() != Rop.BRANCH_NONE) { 51 // move-result-pseudo is required here 52 throw new IllegalArgumentException 53 ("can't mix branchingness with result"); 54 } 55 } 56 57 /** 58 * Constructs a single-source instance. 59 * 60 * @param opcode {@code non-null;} the opcode 61 * @param position {@code non-null;} source position 62 * @param result {@code null-ok;} spec for the result, if any 63 * @param source {@code non-null;} spec for the source 64 */ 65 public PlainInsn(Rop opcode, SourcePosition position, RegisterSpec result, 66 RegisterSpec source) { 67 this(opcode, position, result, RegisterSpecList.make(source)); 68 } 69 70 /** {@inheritDoc} */ 71 @Override 72 public TypeList getCatches() { 73 return StdTypeList.EMPTY; 74 } 75 76 /** {@inheritDoc} */ 77 @Override 78 public void accept(Visitor visitor) { 79 visitor.visitPlainInsn(this); 80 } 81 82 /** {@inheritDoc} */ 83 @Override 84 public Insn withAddedCatch(Type type) { 85 throw new UnsupportedOperationException("unsupported"); 86 } 87 88 /** {@inheritDoc} */ 89 @Override 90 public Insn withRegisterOffset(int delta) { 91 return new PlainInsn(getOpcode(), getPosition(), 92 getResult().withOffset(delta), 93 getSources().withOffset(delta)); 94 } 95 96 /** {@inheritDoc} */ 97 @Override 98 public Insn withLastSourceLiteral() { 99 RegisterSpecList sources = getSources(); 100 int szSources = sources.size(); 101 102 if (szSources == 0) { 103 return this; 104 } 105 106 TypeBearer lastType = sources.get(szSources - 1).getTypeBearer(); 107 108 if (!lastType.isConstant()) { 109 return this; 110 } 111 112 Constant cst = (Constant) lastType; 113 114 RegisterSpecList newSources = sources.withoutLast(); 115 116 Rop newRop; 117 try { 118 newRop = Rops.ropFor(getOpcode().getOpcode(), 119 getResult(), newSources, (Constant)lastType); 120 } catch (IllegalArgumentException ex) { 121 // There's no rop for this case 122 return this; 123 } 124 125 return new PlainCstInsn(newRop, getPosition(), 126 getResult(), newSources, cst); 127 } 128 129 130 /** {@inheritDoc} */ 131 @Override 132 public Insn withNewRegisters(RegisterSpec result, 133 RegisterSpecList sources) { 134 135 return new PlainInsn(getOpcode(), getPosition(), 136 result, 137 sources); 138 139 } 140 } 141