1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.code; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.dex.DexOptions; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.io.Opcodes; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.BasicBlock; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.BasicBlockList; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.FillArrayDataInsn; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.Insn; 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.LocalVariableInfo; 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.PlainCstInsn; 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.PlainInsn; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegOps; 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpec; 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpecList; 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpecSet; 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.Rop; 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RopMethod; 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.SourcePosition; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.SwitchInsn; 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.ThrowingCstInsn; 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.ThrowingInsn; 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.Constant; 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstInteger; 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Bits; 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.IntList; 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.ArrayList; 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Translator from {@link RopMethod} to {@link DalvCode}. The {@link 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * #translate} method is the thing to call on this class. 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class RopTranslator { 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} options for dex output */ 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final DexOptions dexOptions; 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} method to translate */ 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final RopMethod method; 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * how much position info to preserve; one of the static 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constants in {@link PositionList} 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int positionInfo; 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code null-ok;} local variable info to use */ 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final LocalVariableInfo locals; 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} container for all the address objects for the method */ 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final BlockAddresses addresses; 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} list of output instructions in-progress */ 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final OutputCollector output; 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} visitor to use during translation */ 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final TranslationVisitor translationVisitor; 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code >= 0;} register count for the method */ 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int regCount; 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code null-ok;} block output order; becomes non-null in {@link #pickOrder} */ 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private int[] order; 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** size, in register units, of all the parameters to this method */ 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int paramSize; 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * true if the parameters to this method happen to be in proper order 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * at the end of the frame (as the optimizer emits them) 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private boolean paramsAreInOrder; 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Translates a {@link RopMethod}. This may modify the given 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * input. 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param method {@code non-null;} the original method 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param positionInfo how much position info to preserve; one of the 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * static constants in {@link PositionList} 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param locals {@code null-ok;} local variable information to use 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param paramSize size, in register units, of all the parameters to 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * this method 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param dexOptions {@code non-null;} options for dex output 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the translated version 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static DalvCode translate(RopMethod method, int positionInfo, 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalVariableInfo locals, int paramSize, DexOptions dexOptions) { 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RopTranslator translator = 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new RopTranslator(method, positionInfo, locals, paramSize, dexOptions); 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return translator.translateAndGetResult(); 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. This method is private. Use {@link #translate}. 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param method {@code non-null;} the original method 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param positionInfo how much position info to preserve; one of the 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * static constants in {@link PositionList} 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param locals {@code null-ok;} local variable information to use 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param paramSize size, in register units, of all the parameters to 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * this method 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param dexOptions {@code non-null;} options for dex output 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private RopTranslator(RopMethod method, int positionInfo, LocalVariableInfo locals, 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int paramSize, DexOptions dexOptions) { 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.dexOptions = dexOptions; 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.method = method; 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.positionInfo = positionInfo; 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.locals = locals; 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.addresses = new BlockAddresses(method); 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.paramSize = paramSize; 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.order = null; 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.paramsAreInOrder = calculateParamsAreInOrder(method, paramSize); 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlockList blocks = method.getBlocks(); 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int bsz = blocks.size(); 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Max possible instructions includes three code address 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * objects per basic block (to the first and last instruction, 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and just past the end of the block), and the possibility of 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * an extra goto at the end of each basic block. 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int maxInsns = (bsz * 3) + blocks.getInstructionCount(); 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (locals != null) { 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * If we're tracking locals, then there's could be another 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * extra instruction per block (for the locals state at the 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * start of the block) as well as one for each interblock 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * local introduction. 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson maxInsns += bsz + locals.getAssignmentCount(); 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * If params are not in order, we will need register space 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * for them before this is all over... 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.regCount = blocks.getRegCount() 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson + (paramsAreInOrder ? 0 : this.paramSize); 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.output = new OutputCollector(dexOptions, maxInsns, bsz * 3, regCount); 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (locals != null) { 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.translationVisitor = 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new LocalVariableAwareTranslationVisitor(output, locals); 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.translationVisitor = new TranslationVisitor(output); 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Checks to see if the move-param instructions that occur in this 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * method happen to slot the params in an order at the top of the 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * stack frame that matches dalvik's calling conventions. This will 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * alway result in "true" for methods that have run through the 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * SSA optimizer. 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param paramSize size, in register units, of all the parameters 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to this method 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static boolean calculateParamsAreInOrder(RopMethod method, 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson final int paramSize) { 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson final boolean[] paramsAreInOrder = { true }; 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson final int initialRegCount = method.getBlocks().getRegCount(); 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * We almost could just check the first block here, but the 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code cf} layer will put in a second move-param in a 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * subsequent block in the case of synchronized methods. 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson method.getBlocks().forEachInsn(new Insn.BaseVisitor() { 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainCstInsn(PlainCstInsn insn) { 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insn.getOpcode().getOpcode()== RegOps.MOVE_PARAM) { 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int param = 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ((CstInteger) insn.getConstant()).getValue(); 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson paramsAreInOrder[0] = paramsAreInOrder[0] 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && ((initialRegCount - paramSize + param) 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson == insn.getResult().getReg()); 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }); 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return paramsAreInOrder[0]; 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Does the translation and returns the result. 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the result 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private DalvCode translateAndGetResult() { 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson pickOrder(); 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson outputInstructions(); 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson StdCatchBuilder catches = 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new StdCatchBuilder(method, order, addresses); 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new DalvCode(positionInfo, output.getFinisher(), catches); 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Performs initial creation of output instructions based on the 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * original blocks. 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void outputInstructions() { 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlockList blocks = method.getBlocks(); 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int[] order = this.order; 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int len = order.length; 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Process the blocks in output order. 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < len; i++) { 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int nextI = i + 1; 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int nextLabel = (nextI == order.length) ? -1 : order[nextI]; 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson outputBlock(blocks.labelToBlock(order[i]), nextLabel); 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #outputInstructions}, which does the processing 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and output of one block. 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param block {@code non-null;} the block to process and output 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param nextLabel {@code >= -1;} the next block that will be processed, or 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code -1} if there is no next block 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void outputBlock(BasicBlock block, int nextLabel) { 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Append the code address for this block. 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CodeAddress startAddress = addresses.getStart(block); 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.add(startAddress); 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Append the local variable state for the block. 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (locals != null) { 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecSet starts = locals.getStarts(block); 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.add(new LocalSnapshot(startAddress.getPosition(), 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson starts)); 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Choose and append an output instruction for each original 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instruction. 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson translationVisitor.setBlock(block, addresses.getLast(block)); 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson block.getInsns().forEach(translationVisitor); 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Insert the block end code address. 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.add(addresses.getEnd(block)); 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Set up for end-of-block activities. 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int succ = block.getPrimarySuccessor(); 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Insn lastInsn = block.getLastInsn(); 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Check for (and possibly correct for) a non-optimal choice of 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * which block will get output next. 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((succ >= 0) && (succ != nextLabel)) { 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The block has a "primary successor" and that primary 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * successor isn't the next block to be output. 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Rop lastRop = lastInsn.getOpcode(); 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((lastRop.getBranchingness() == Rop.BRANCH_IF) && 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson (block.getSecondarySuccessor() == nextLabel)) { 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The block ends with an "if" of some sort, and its 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * secondary successor (the "then") is in fact the 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * next block to output. So, reverse the sense of 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the test, so that we can just emit the next block 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * without an interstitial goto. 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.reverseBranch(1, addresses.getStart(succ)); 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Our only recourse is to add a goto here to get the 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * flow to be correct. 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TargetInsn insn = 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new TargetInsn(Dops.GOTO, lastInsn.getPosition(), 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList.EMPTY, 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addresses.getStart(succ)); 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.add(insn); 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Picks an order for the blocks by doing "trace" analysis. 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void pickOrder() { 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlockList blocks = method.getBlocks(); 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sz = blocks.size(); 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int maxLabel = blocks.getMaxLabel(); 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int[] workSet = Bits.makeBitSet(maxLabel); 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int[] tracebackSet = Bits.makeBitSet(maxLabel); 317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < sz; i++) { 319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlock one = blocks.get(i); 320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Bits.set(workSet, one.getLabel()); 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int[] order = new int[sz]; 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int at = 0; 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Starting with the designated "first label" (that is, the 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * first block of the method), add that label to the order, 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and then pick its first as-yet unordered successor to 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * immediately follow it, giving top priority to the primary 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * (aka default) successor (if any). Keep following successors 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * until the trace runs out of possibilities. Then, continue 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * by finding an unordered chain containing the first as-yet 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * unordered block, and adding it to the order, and so on. 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int label = method.getFirstLabel(); 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label != -1; 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label = Bits.findFirst(workSet, 0)) { 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Attempt to trace backward from the chosen block to an 342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * as-yet unordered predecessor which lists the chosen 343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * block as its primary successor, and so on, until we 344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * fail to find such an unordered predecessor. Start the 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * trace with that block. Note that the first block in the 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * method has no predecessors, so in that case this loop 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * will simply terminate with zero iterations and without 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * picking a new starter block. 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson traceBack: 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (;;) { 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IntList preds = method.labelToPredecessors(label); 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int psz = preds.size(); 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < psz; i++) { 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int predLabel = preds.get(i); 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (Bits.get(tracebackSet, predLabel)) { 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * We found a predecessor loop; stop tracing back 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * from here. 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!Bits.get(workSet, predLabel)) { 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This one's already ordered. 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson continue; 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlock pred = blocks.labelToBlock(predLabel); 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (pred.getPrimarySuccessor() == label) { 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Found one! 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label = predLabel; 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Bits.set(tracebackSet, label); 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson continue traceBack; 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Failed to find a better block to start the trace. 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Trace a path from the chosen block to one of its 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * unordered successors (hopefully the primary), and so 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * on, until we run out of unordered successors. 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson while (label != -1) { 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Bits.clear(workSet, label); 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Bits.clear(tracebackSet, label); 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson order[at] = label; 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson at++; 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlock one = blocks.labelToBlock(label); 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson BasicBlock preferredBlock = blocks.preferredSuccessorOf(one); 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (preferredBlock == null) { 399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int preferred = preferredBlock.getLabel(); 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int primary = one.getPrimarySuccessor(); 404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (Bits.get(workSet, preferred)) { 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Order the current block's preferred successor 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * next, as it has yet to be scheduled. 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label = preferred; 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if ((primary != preferred) && (primary >= 0) 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && Bits.get(workSet, primary)) { 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The primary is available, so use that. 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label = primary; 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * There's no obvious candidate, so pick the first 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * one that's available, if any. 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IntList successors = one.getSuccessors(); 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int ssz = successors.size(); 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label = -1; 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < ssz; i++) { 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int candidate = successors.get(i); 427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (Bits.get(workSet, candidate)) { 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson label = candidate; 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (at != sz) { 437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // There was a duplicate block label. 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.order = order; 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the complete register list (result and sources) out of a 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * given rop instruction. For insns that are commutative, have 447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * two register sources, and have a source equal to the result, 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * place that source first. 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} instruction in question 451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the instruction's complete register list 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static RegisterSpecList getRegs(Insn insn) { 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getRegs(insn, insn.getResult()); 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the complete register list (result and sources) out of a 459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * given rop instruction. For insns that are commutative, have 460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * two register sources, and have a source equal to the result, 461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * place that source first. 462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} instruction in question 464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param resultReg {@code null-ok;} the real result to use (ignore the insn's) 465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the instruction's complete register list 466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static RegisterSpecList getRegs(Insn insn, 468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec resultReg) { 469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList regs = insn.getSources(); 470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insn.getOpcode().isCommutative() 472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && (regs.size() == 2) 473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && (resultReg.getReg() == regs.get(1).getReg())) { 474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * For commutative ops which have two register sources, 477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if the second source is the same register as the result, 478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * swap the sources so that an opcode of form 12x can be selected 479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instead of one of form 23x 480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson regs = RegisterSpecList.make(regs.get(1), regs.get(0)); 483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (resultReg == null) { 486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return regs; 487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return regs.withFirst(resultReg); 490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Instruction visitor class for doing the instruction translation per se. 494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private class TranslationVisitor implements Insn.Visitor { 496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} list of output instructions in-progress */ 497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final OutputCollector output; 498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} basic block being worked on */ 500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private BasicBlock block; 501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} code address for the salient last instruction of the 504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * block (used before switches and throwing instructions) 505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private CodeAddress lastAddress; 507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param output {@code non-null;} destination for instruction output 512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TranslationVisitor(OutputCollector output) { 514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.output = output; 515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Sets the block currently being worked on. 519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param block {@code non-null;} the block 521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param lastAddress {@code non-null;} code address for the salient 522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * last instruction of the block 523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setBlock(BasicBlock block, CodeAddress lastAddress) { 525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.block = block; 526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.lastAddress = lastAddress; 527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainInsn(PlainInsn insn) { 531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Rop rop = insn.getOpcode(); 532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.getOpcode() == RegOps.MARK_LOCAL) { 533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Ignore these. They're dealt with by 535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the LocalVariableAwareTranslationVisitor 536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.getOpcode() == RegOps.MOVE_RESULT_PSEUDO) { 540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // These get skipped 541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Dop opcode = RopToDop.dopFor(insn); 546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsn di; 547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson switch (rop.getBranchingness()) { 549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Rop.BRANCH_NONE: 550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Rop.BRANCH_RETURN: 551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Rop.BRANCH_THROW: { 552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson di = new SimpleInsn(opcode, pos, getRegs(insn)); 553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Rop.BRANCH_GOTO: { 556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Code in the main translation loop will emit a 558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * goto if necessary (if the branch isn't to the 559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * immediately subsequent block). 560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Rop.BRANCH_IF: { 564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int target = block.getSuccessors().get(1); 565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson di = new TargetInsn(opcode, pos, getRegs(insn), 566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addresses.getStart(target)); 567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson break; 568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson default: { 570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(di); 575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainCstInsn(PlainCstInsn insn) { 579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Dop opcode = RopToDop.dopFor(insn); 581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Rop rop = insn.getOpcode(); 582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int ropOpcode = rop.getOpcode(); 583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsn di; 584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.getBranchingness() != Rop.BRANCH_NONE) { 586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (ropOpcode == RegOps.MOVE_PARAM) { 590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!paramsAreInOrder) { 591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Parameters are not in order at the top of the reg space. 593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * We need to add moves. 594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec dest = insn.getResult(); 597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int param = 598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ((CstInteger) insn.getConstant()).getValue(); 599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec source = 600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec.make(regCount - paramSize + param, 601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson dest.getType()); 602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson di = new SimpleInsn(opcode, pos, 603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList.make(dest, source)); 604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(di); 605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // No moves required for the parameters 608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList regs = getRegs(insn); 609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson di = new CstInsn(opcode, pos, regs, insn.getConstant()); 610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(di); 611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitSwitchInsn(SwitchInsn insn) { 616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IntList cases = insn.getCases(); 618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IntList successors = block.getSuccessors(); 619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int casesSz = cases.size(); 620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int succSz = successors.size(); 621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int primarySuccessor = block.getPrimarySuccessor(); 622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Check the assumptions that the number of cases is one 625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * less than the number of successors and that the last 626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * successor in the list is the primary (in this case, the 627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * default). This test is here to guard against forgetting 628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to change this code if the way switch instructions are 629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constructed also gets changed. 630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((casesSz != (succSz - 1)) || 632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson (primarySuccessor != successors.get(casesSz))) { 633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CodeAddress[] switchTargets = new CodeAddress[casesSz]; 637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < casesSz; i++) { 639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int label = successors.get(i); 640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson switchTargets[i] = addresses.getStart(label); 641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CodeAddress dataAddress = new CodeAddress(pos); 644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SwitchData dataInsn = 645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new SwitchData(pos, lastAddress, cases, switchTargets); 646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Dop opcode = dataInsn.isPacked() ? 647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Dops.PACKED_SWITCH : Dops.SPARSE_SWITCH; 648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TargetInsn switchInsn = 649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new TargetInsn(opcode, pos, getRegs(insn), dataAddress); 650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(lastAddress); 652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(switchInsn); 653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutputSuffix(new OddSpacer(pos)); 655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutputSuffix(dataAddress); 656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutputSuffix(dataInsn); 657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 659579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 660579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Looks forward to the current block's primary successor, returning 661579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the RegisterSpec of the result of the move-result-pseudo at the 662579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * top of that block or null if none. 663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 664579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} result of move-result-pseudo at the beginning of 665579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * primary successor 666579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 667579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private RegisterSpec getNextMoveResultPseudo() 668579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson { 669579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int label = block.getPrimarySuccessor(); 670579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 671579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (label < 0) { 672579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 673579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 674579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 675579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Insn insn 676579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson = method.getBlocks().labelToBlock(label).getInsns().get(0); 677579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 678579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (insn.getOpcode().getOpcode() != RegOps.MOVE_RESULT_PSEUDO) { 679579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 680579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 681579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return insn.getResult(); 682579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 683579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 684579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 685579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 686579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingCstInsn(ThrowingCstInsn insn) { 687579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 688579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Dop opcode = RopToDop.dopFor(insn); 689579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Rop rop = insn.getOpcode(); 690579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Constant cst = insn.getConstant(); 691579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 692579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.getBranchingness() != Rop.BRANCH_THROW) { 693579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 694579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 695579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 696579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(lastAddress); 697579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 698579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.isCallLike()) { 699579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList regs = insn.getSources(); 700579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsn di = new CstInsn(opcode, pos, regs, cst); 701579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 702579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(di); 703579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 704579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec realResult = getNextMoveResultPseudo(); 705579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 706579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList regs = getRegs(insn, realResult); 707579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsn di; 708579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 709579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean hasResult = opcode.hasResult() 710579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson || (rop.getOpcode() == RegOps.CHECK_CAST); 711579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 712579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (hasResult != (realResult != null)) { 713579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException( 714579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "Insn with result/move-result-pseudo mismatch " + 715579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson insn); 716579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 717579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 718579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((rop.getOpcode() == RegOps.NEW_ARRAY) && 719579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson (opcode.getOpcode() != Opcodes.NEW_ARRAY)) { 720579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 721579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * It's a type-specific new-array-<primitive>, and 722579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * so it should be turned into a SimpleInsn (no 723579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * constant ref as it's implicit). 724579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 725579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson di = new SimpleInsn(opcode, pos, regs); 726579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 727579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 728579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This is the general case for constant-bearing 729579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instructions. 730579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 731579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson di = new CstInsn(opcode, pos, regs, cst); 732579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 733579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 734579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(di); 735579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 736579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 737579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 738579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 739579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingInsn(ThrowingInsn insn) { 740579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 741579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Dop opcode = RopToDop.dopFor(insn); 742579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Rop rop = insn.getOpcode(); 743579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec realResult; 744579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 745579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.getBranchingness() != Rop.BRANCH_THROW) { 746579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 747579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 748579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 749579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson realResult = getNextMoveResultPseudo(); 750579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 751579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (opcode.hasResult() != (realResult != null)) { 752579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException( 753579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "Insn with result/move-result-pseudo mismatch" + insn); 754579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 755579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 756579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(lastAddress); 757579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 758579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson DalvInsn di = new SimpleInsn(opcode, pos, 759579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson getRegs(insn, realResult)); 760579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 761579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(di); 762579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 763579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 764579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 765579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitFillArrayDataInsn(FillArrayDataInsn insn) { 766579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SourcePosition pos = insn.getPosition(); 767579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Constant cst = insn.getConstant(); 768579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ArrayList<Constant> values = insn.getInitValues(); 769579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Rop rop = insn.getOpcode(); 770579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 771579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (rop.getBranchingness() != Rop.BRANCH_NONE) { 772579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("shouldn't happen"); 773579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 774579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson CodeAddress dataAddress = new CodeAddress(pos); 775579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ArrayData dataInsn = 776579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new ArrayData(pos, lastAddress, values, cst); 777579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 778579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TargetInsn fillArrayDataInsn = 779579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new TargetInsn(Dops.FILL_ARRAY_DATA, pos, getRegs(insn), 780579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson dataAddress); 781579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 782579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(lastAddress); 783579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(fillArrayDataInsn); 784579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 785579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutputSuffix(new OddSpacer(pos)); 786579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutputSuffix(dataAddress); 787579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutputSuffix(dataInsn); 788579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 789579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 790579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 791579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Adds to the output. 792579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 793579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} instruction to add 794579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 795579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected void addOutput(DalvInsn insn) { 796579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.add(insn); 797579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 798579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 799579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 800579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Adds to the output suffix. 801579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 802579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} instruction to add 803579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 804579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected void addOutputSuffix(DalvInsn insn) { 805579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output.addSuffix(insn); 806579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 807579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 808579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 809579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 810579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Instruction visitor class for doing instruction translation with 811579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * local variable tracking 812579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 813579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private class LocalVariableAwareTranslationVisitor 814579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson extends TranslationVisitor { 815579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} local variable info */ 816579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private LocalVariableInfo locals; 817579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 818579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 819579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 820579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 821579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param output {@code non-null;} destination for instruction output 822579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param locals {@code non-null;} the local variable info 823579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 824579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public LocalVariableAwareTranslationVisitor(OutputCollector output, 825579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalVariableInfo locals) { 826579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super(output); 827579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.locals = locals; 828579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 829579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 830579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 831579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 832579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainInsn(PlainInsn insn) { 833579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super.visitPlainInsn(insn); 834579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addIntroductionIfNecessary(insn); 835579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 836579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 837579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 838579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 839579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainCstInsn(PlainCstInsn insn) { 840579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super.visitPlainCstInsn(insn); 841579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addIntroductionIfNecessary(insn); 842579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 843579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 844579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 845579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 846579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitSwitchInsn(SwitchInsn insn) { 847579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super.visitSwitchInsn(insn); 848579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addIntroductionIfNecessary(insn); 849579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 850579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 851579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 852579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 853579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingCstInsn(ThrowingCstInsn insn) { 854579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super.visitThrowingCstInsn(insn); 855579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addIntroductionIfNecessary(insn); 856579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 857579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 858579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 859579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 860579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingInsn(ThrowingInsn insn) { 861579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super.visitThrowingInsn(insn); 862579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addIntroductionIfNecessary(insn); 863579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 864579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 865579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 866579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Adds a {@link LocalStart} to the output if the given 867579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instruction in fact introduces a local variable. 868579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 869579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} instruction in question 870579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 871579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void addIntroductionIfNecessary(Insn insn) { 872579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec spec = locals.getAssignment(insn); 873579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 874579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (spec != null) { 875579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addOutput(new LocalStart(insn.getPosition(), spec)); 876579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 877579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 878579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 879579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 880