1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.BasicBlock; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.BasicBlockList; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.FillArrayDataInsn; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.Insn; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.LocalVariableInfo; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.PlainCstInsn; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.PlainInsn; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegOps; 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpec; 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpecList; 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RegisterSpecSet; 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.Rop; 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.RopMethod; 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.SourcePosition; 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.SwitchInsn; 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.ThrowingCstInsn; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.code.ThrowingInsn; 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstInteger; 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type; 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Bits; 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.IntList; 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.ArrayList; 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Translator from {@link RopMethod} to {@link DalvCode}. The {@link 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * #translate} method is the thing to call on this class. 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class RopTranslator { 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} method to translate */ 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final RopMethod method; 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * how much position info to preserve; one of the static 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constants in {@link PositionList} 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int positionInfo; 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} local variable info to use */ 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final LocalVariableInfo locals; 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} container for all the address objects for the method */ 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final BlockAddresses addresses; 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of output instructions in-progress */ 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final OutputCollector output; 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} visitor to use during translation */ 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final TranslationVisitor translationVisitor; 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} register count for the method */ 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int regCount; 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} block output order; becomes non-null in {@link #pickOrder} */ 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int[] order; 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** size, in register units, of all the parameters to this method */ 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int paramSize; 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * true if the parameters to this method happen to be in proper order 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * at the end of the frame (as the optimizer emits them) 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private boolean paramsAreInOrder; 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Translates a {@link RopMethod}. This may modify the given 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * input. 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param method {@code non-null;} the original method 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param positionInfo how much position info to preserve; one of the 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * static constants in {@link PositionList} 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param locals {@code null-ok;} local variable information to use 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param paramSize size, in register units, of all the parameters to 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this method 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the translated version 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static DalvCode translate(RopMethod method, int positionInfo, 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalVariableInfo locals, int paramSize) { 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RopTranslator translator = 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new RopTranslator(method, positionInfo, locals, 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul paramSize); 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return translator.translateAndGetResult(); 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. This method is private. Use {@link #translate}. 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param method {@code non-null;} the original method 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param positionInfo how much position info to preserve; one of the 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * static constants in {@link PositionList} 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param locals {@code null-ok;} local variable information to use 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param paramSize size, in register units, of all the parameters to 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this method 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private RopTranslator(RopMethod method, int positionInfo, 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalVariableInfo locals, int paramSize) { 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.method = method; 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.positionInfo = positionInfo; 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.locals = locals; 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.addresses = new BlockAddresses(method); 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.paramSize = paramSize; 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.order = null; 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.paramsAreInOrder = calculateParamsAreInOrder(method, paramSize); 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlockList blocks = method.getBlocks(); 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int bsz = blocks.size(); 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Max possible instructions includes three code address 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * objects per basic block (to the first and last instruction, 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and just past the end of the block), and the possibility of 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * an extra goto at the end of each basic block. 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int maxInsns = (bsz * 3) + blocks.getInstructionCount(); 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (locals != null) { 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * If we're tracking locals, then there's could be another 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * extra instruction per block (for the locals state at the 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * start of the block) as well as one for each interblock 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * local introduction. 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul maxInsns += bsz + locals.getAssignmentCount(); 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * If params are not in order, we will need register space 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * for them before this is all over... 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.regCount = blocks.getRegCount() 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul + (paramsAreInOrder ? 0 : this.paramSize); 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.output = new OutputCollector(maxInsns, bsz * 3, regCount); 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (locals != null) { 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.translationVisitor = 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new LocalVariableAwareTranslationVisitor(output, locals); 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.translationVisitor = new TranslationVisitor(output); 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Checks to see if the move-param instructions that occur in this 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method happen to slot the params in an order at the top of the 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * stack frame that matches dalvik's calling conventions. This will 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * alway result in "true" for methods that have run through the 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * SSA optimizer. 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param paramSize size, in register units, of all the parameters 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to this method 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static boolean calculateParamsAreInOrder(RopMethod method, 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul final int paramSize) { 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul final boolean[] paramsAreInOrder = { true }; 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul final int initialRegCount = method.getBlocks().getRegCount(); 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * We almost could just check the first block here, but the 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code cf} layer will put in a second move-param in a 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * subsequent block in the case of synchronized methods. 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul method.getBlocks().forEachInsn(new Insn.BaseVisitor() { 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainCstInsn(PlainCstInsn insn) { 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insn.getOpcode().getOpcode()== RegOps.MOVE_PARAM) { 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int param = 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ((CstInteger) insn.getConstant()).getValue(); 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul paramsAreInOrder[0] = paramsAreInOrder[0] 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && ((initialRegCount - paramSize + param) 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul == insn.getResult().getReg()); 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul }); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return paramsAreInOrder[0]; 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Does the translation and returns the result. 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the result 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private DalvCode translateAndGetResult() { 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul pickOrder(); 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul outputInstructions(); 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StdCatchBuilder catches = 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new StdCatchBuilder(method, order, addresses); 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new DalvCode(positionInfo, output.getFinisher(), catches); 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Performs initial creation of output instructions based on the 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * original blocks. 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void outputInstructions() { 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlockList blocks = method.getBlocks(); 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int[] order = this.order; 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = order.length; 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Process the blocks in output order. 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int nextI = i + 1; 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int nextLabel = (nextI == order.length) ? -1 : order[nextI]; 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul outputBlock(blocks.labelToBlock(order[i]), nextLabel); 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #outputInstructions}, which does the processing 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and output of one block. 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param block {@code non-null;} the block to process and output 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param nextLabel {@code >= -1;} the next block that will be processed, or 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code -1} if there is no next block 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void outputBlock(BasicBlock block, int nextLabel) { 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Append the code address for this block. 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CodeAddress startAddress = addresses.getStart(block); 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.add(startAddress); 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Append the local variable state for the block. 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (locals != null) { 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecSet starts = locals.getStarts(block); 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.add(new LocalSnapshot(startAddress.getPosition(), 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul starts)); 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Choose and append an output instruction for each original 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instruction. 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul translationVisitor.setBlock(block, addresses.getLast(block)); 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul block.getInsns().forEach(translationVisitor); 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Insert the block end code address. 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.add(addresses.getEnd(block)); 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Set up for end-of-block activities. 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int succ = block.getPrimarySuccessor(); 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Insn lastInsn = block.getLastInsn(); 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Check for (and possibly correct for) a non-optimal choice of 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which block will get output next. 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((succ >= 0) && (succ != nextLabel)) { 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The block has a "primary successor" and that primary 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * successor isn't the next block to be output. 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Rop lastRop = lastInsn.getOpcode(); 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((lastRop.getBranchingness() == Rop.BRANCH_IF) && 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (block.getSecondarySuccessor() == nextLabel)) { 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The block ends with an "if" of some sort, and its 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * secondary successor (the "then") is in fact the 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * next block to output. So, reverse the sense of 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the test, so that we can just emit the next block 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * without an interstitial goto. 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.reverseBranch(1, addresses.getStart(succ)); 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Our only recourse is to add a goto here to get the 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * flow to be correct. 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TargetInsn insn = 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new TargetInsn(Dops.GOTO, lastInsn.getPosition(), 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList.EMPTY, 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addresses.getStart(succ)); 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.add(insn); 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Picks an order for the blocks by doing "trace" analysis. 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void pickOrder() { 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlockList blocks = method.getBlocks(); 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = blocks.size(); 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int maxLabel = blocks.getMaxLabel(); 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int[] workSet = Bits.makeBitSet(maxLabel); 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int[] tracebackSet = Bits.makeBitSet(maxLabel); 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock one = blocks.get(i); 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Bits.set(workSet, one.getLabel()); 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int[] order = new int[sz]; 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int at = 0; 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Starting with the designated "first label" (that is, the 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * first block of the method), add that label to the order, 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and then pick its first as-yet unordered successor to 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * immediately follow it, giving top priority to the primary 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * (aka default) successor (if any). Keep following successors 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * until the trace runs out of possibilities. Then, continue 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * by finding an unordered chain containing the first as-yet 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * unordered block, and adding it to the order, and so on. 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int label = method.getFirstLabel(); 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label != -1; 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label = Bits.findFirst(workSet, 0)) { 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Attempt to trace backward from the chosen block to an 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * as-yet unordered predecessor which lists the chosen 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * block as its primary successor, and so on, until we 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * fail to find such an unordered predecessor. Start the 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * trace with that block. Note that the first block in the 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method has no predecessors, so in that case this loop 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * will simply terminate with zero iterations and without 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * picking a new starter block. 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul traceBack: 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (;;) { 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList preds = method.labelToPredecessors(label); 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int psz = preds.size(); 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < psz; i++) { 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int predLabel = preds.get(i); 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (Bits.get(tracebackSet, predLabel)) { 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * We found a predecessor loop; stop tracing back 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * from here. 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!Bits.get(workSet, predLabel)) { 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This one's already ordered. 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock pred = blocks.labelToBlock(predLabel); 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (pred.getPrimarySuccessor() == label) { 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Found one! 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label = predLabel; 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Bits.set(tracebackSet, label); 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue traceBack; 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Failed to find a better block to start the trace. 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Trace a path from the chosen block to one of its 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * unordered successors (hopefully the primary), and so 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * on, until we run out of unordered successors. 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while (label != -1) { 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Bits.clear(workSet, label); 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Bits.clear(tracebackSet, label); 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul order[at] = label; 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul at++; 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock one = blocks.labelToBlock(label); 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul BasicBlock preferredBlock = blocks.preferredSuccessorOf(one); 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (preferredBlock == null) { 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int preferred = preferredBlock.getLabel(); 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int primary = one.getPrimarySuccessor(); 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (Bits.get(workSet, preferred)) { 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Order the current block's preferred successor 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * next, as it has yet to be scheduled. 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label = preferred; 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if ((primary != preferred) && (primary >= 0) 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && Bits.get(workSet, primary)) { 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The primary is available, so use that. 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label = primary; 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * There's no obvious candidate, so pick the first 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * one that's available, if any. 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList successors = one.getSuccessors(); 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int ssz = successors.size(); 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label = -1; 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < ssz; i++) { 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int candidate = successors.get(i); 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (Bits.get(workSet, candidate)) { 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul label = candidate; 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (at != sz) { 430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // There was a duplicate block label. 431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.order = order; 435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the complete register list (result and sources) out of a 439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given rop instruction. For insns that are commutative, have 440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * two register sources, and have a source equal to the result, 441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * place that source first. 442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} instruction in question 444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the instruction's complete register list 445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static RegisterSpecList getRegs(Insn insn) { 447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return getRegs(insn, insn.getResult()); 448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the complete register list (result and sources) out of a 452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given rop instruction. For insns that are commutative, have 453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * two register sources, and have a source equal to the result, 454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * place that source first. 455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} instruction in question 457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param resultReg {@code null-ok;} the real result to use (ignore the insn's) 458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the instruction's complete register list 459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static RegisterSpecList getRegs(Insn insn, 461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec resultReg) { 462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = insn.getSources(); 463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insn.getOpcode().isCommutative() 465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && (regs.size() == 2) 466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && (resultReg.getReg() == regs.get(1).getReg())) { 467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * For commutative ops which have two register sources, 470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if the second source is the same register as the result, 471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * swap the sources so that an opcode of form 12x can be selected 472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instead of one of form 23x 473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul regs = RegisterSpecList.make(regs.get(1), regs.get(0)); 476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (resultReg == null) { 479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return regs; 480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return regs.withFirst(resultReg); 483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Instruction visitor class for doing the instruction translation per se. 487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private class TranslationVisitor implements Insn.Visitor { 489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of output instructions in-progress */ 490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final OutputCollector output; 491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} basic block being worked on */ 493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private BasicBlock block; 494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} code address for the salient last instruction of the 497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * block (used before switches and throwing instructions) 498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private CodeAddress lastAddress; 500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param output {@code non-null;} destination for instruction output 505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public TranslationVisitor(OutputCollector output) { 507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.output = output; 508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Sets the block currently being worked on. 512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param block {@code non-null;} the block 514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param lastAddress {@code non-null;} code address for the salient 515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * last instruction of the block 516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void setBlock(BasicBlock block, CodeAddress lastAddress) { 518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.block = block; 519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.lastAddress = lastAddress; 520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainInsn(PlainInsn insn) { 524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Rop rop = insn.getOpcode(); 525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.getOpcode() == RegOps.MARK_LOCAL) { 526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Ignore these. They're dealt with by 528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the LocalVariableAwareTranslationVisitor 529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 530917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 531917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 532917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.getOpcode() == RegOps.MOVE_RESULT_PSEUDO) { 533917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // These get skipped 534917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 535917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 536917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 537917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 538917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Dop opcode = RopToDop.dopFor(insn); 539917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DalvInsn di; 540917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 541917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul switch (rop.getBranchingness()) { 542917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case Rop.BRANCH_NONE: 543917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case Rop.BRANCH_RETURN: 544917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case Rop.BRANCH_THROW: { 545917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul di = new SimpleInsn(opcode, pos, getRegs(insn)); 546917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 547917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 548917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case Rop.BRANCH_GOTO: { 549917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 550917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Code in the main translation loop will emit a 551917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * goto if necessary (if the branch isn't to the 552917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * immediately subsequent block). 553917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 554917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 555917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 556917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul case Rop.BRANCH_IF: { 557917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int target = block.getSuccessors().get(1); 558917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul di = new TargetInsn(opcode, pos, getRegs(insn), 559917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addresses.getStart(target)); 560917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 561917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 562917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul default: { 563917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 564917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 565917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 566917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 567917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(di); 568917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 569917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 570917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 571917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainCstInsn(PlainCstInsn insn) { 572917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 573917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Dop opcode = RopToDop.dopFor(insn); 574917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Rop rop = insn.getOpcode(); 575917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int ropOpcode = rop.getOpcode(); 576917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DalvInsn di; 577917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 578917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.getBranchingness() != Rop.BRANCH_NONE) { 579917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 580917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 581917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 582917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (ropOpcode == RegOps.MOVE_PARAM) { 583917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!paramsAreInOrder) { 584917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 585917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Parameters are not in order at the top of the reg space. 586917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * We need to add moves. 587917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 588917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 589917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec dest = insn.getResult(); 590917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int param = 591917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ((CstInteger) insn.getConstant()).getValue(); 592917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec source = 593917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec.make(regCount - paramSize + param, 594917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul dest.getType()); 595917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul di = new SimpleInsn(opcode, pos, 596917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList.make(dest, source)); 597917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(di); 598917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 599917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 600917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // No moves required for the parameters 601917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = getRegs(insn); 602917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul di = new CstInsn(opcode, pos, regs, insn.getConstant()); 603917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(di); 604917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 605917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 606917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 607917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 608917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitSwitchInsn(SwitchInsn insn) { 609917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 610917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList cases = insn.getCases(); 611917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul IntList successors = block.getSuccessors(); 612917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int casesSz = cases.size(); 613917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int succSz = successors.size(); 614917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int primarySuccessor = block.getPrimarySuccessor(); 615917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 616917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 617917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Check the assumptions that the number of cases is one 618917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * less than the number of successors and that the last 619917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * successor in the list is the primary (in this case, the 620917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * default). This test is here to guard against forgetting 621917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to change this code if the way switch instructions are 622917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constructed also gets changed. 623917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 624917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((casesSz != (succSz - 1)) || 625917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (primarySuccessor != successors.get(casesSz))) { 626917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 627917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 628917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 629917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CodeAddress[] switchTargets = new CodeAddress[casesSz]; 630917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 631917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < casesSz; i++) { 632917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int label = successors.get(i); 633917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul switchTargets[i] = addresses.getStart(label); 634917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 635917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 636917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CodeAddress dataAddress = new CodeAddress(pos); 637917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SwitchData dataInsn = 638917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new SwitchData(pos, lastAddress, cases, switchTargets); 639917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Dop opcode = dataInsn.isPacked() ? 640917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Dops.PACKED_SWITCH : Dops.SPARSE_SWITCH; 641917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TargetInsn switchInsn = 642917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new TargetInsn(opcode, pos, getRegs(insn), dataAddress); 643917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 644917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(lastAddress); 645917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(switchInsn); 646917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 647917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutputSuffix(new OddSpacer(pos)); 648917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutputSuffix(dataAddress); 649917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutputSuffix(dataInsn); 650917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 651917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 652917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 653917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Looks forward to the current block's primary successor, returning 654917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the RegisterSpec of the result of the move-result-pseudo at the 655917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * top of that block or null if none. 656917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 657917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} result of move-result-pseudo at the beginning of 658917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * primary successor 659917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 660917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private RegisterSpec getNextMoveResultPseudo() 661917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul { 662917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int label = block.getPrimarySuccessor(); 663917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 664917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (label < 0) { 665917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 666917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 667917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 668917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Insn insn 669917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul = method.getBlocks().labelToBlock(label).getInsns().get(0); 670917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 671917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (insn.getOpcode().getOpcode() != RegOps.MOVE_RESULT_PSEUDO) { 672917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 673917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 674917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return insn.getResult(); 675917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 676917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 677917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 678917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 679917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingCstInsn(ThrowingCstInsn insn) { 680917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 681917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Dop opcode = RopToDop.dopFor(insn); 682917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Rop rop = insn.getOpcode(); 683917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Constant cst = insn.getConstant(); 684917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 685917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.getBranchingness() != Rop.BRANCH_THROW) { 686917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 687917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 688917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 689917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(lastAddress); 690917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 691917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.isCallLike()) { 692917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = insn.getSources(); 693917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DalvInsn di = new CstInsn(opcode, pos, regs, cst); 694917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 695917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(di); 696917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 697917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec realResult = getNextMoveResultPseudo(); 698917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 699917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList regs = getRegs(insn, realResult); 700917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DalvInsn di; 701917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 702917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean hasResult = opcode.hasResult() 703917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul || (rop.getOpcode() == RegOps.CHECK_CAST); 704917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 705917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (hasResult != (realResult != null)) { 706917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException( 707917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "Insn with result/move-result-pseudo mismatch " + 708917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul insn); 709917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 710917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 711917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((rop.getOpcode() == RegOps.NEW_ARRAY) && 712917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (opcode.getOpcode() != DalvOps.NEW_ARRAY)) { 713917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 714917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * It's a type-specific new-array-<primitive>, and 715917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * so it should be turned into a SimpleInsn (no 716917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * constant ref as it's implicit). 717917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 718917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul di = new SimpleInsn(opcode, pos, regs); 719917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 720917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 721917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * This is the general case for constant-bearing 722917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instructions. 723917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 724917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul di = new CstInsn(opcode, pos, regs, cst); 725917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 726917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 727917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(di); 728917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 729917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 730917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 731917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 732917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingInsn(ThrowingInsn insn) { 733917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 734917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Dop opcode = RopToDop.dopFor(insn); 735917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Rop rop = insn.getOpcode(); 736917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec realResult; 737917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 738917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.getBranchingness() != Rop.BRANCH_THROW) { 739917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 740917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 741917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 742917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul realResult = getNextMoveResultPseudo(); 743917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 744917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (opcode.hasResult() != (realResult != null)) { 745917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException( 746917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "Insn with result/move-result-pseudo mismatch" + insn); 747917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 748917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 749917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(lastAddress); 750917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 751917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul DalvInsn di = new SimpleInsn(opcode, pos, 752917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul getRegs(insn, realResult)); 753917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 754917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(di); 755917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 756917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 757917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 758917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitFillArrayDataInsn(FillArrayDataInsn insn) { 759917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul SourcePosition pos = insn.getPosition(); 760917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Constant cst = insn.getConstant(); 761917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayList<Constant> values = insn.getInitValues(); 762917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Rop rop = insn.getOpcode(); 763917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 764917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (rop.getBranchingness() != Rop.BRANCH_NONE) { 765917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new RuntimeException("shouldn't happen"); 766917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 767917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul CodeAddress dataAddress = new CodeAddress(pos); 768917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ArrayData dataInsn = 769917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new ArrayData(pos, lastAddress, values, cst); 770917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 771917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TargetInsn fillArrayDataInsn = 772917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new TargetInsn(Dops.FILL_ARRAY_DATA, pos, getRegs(insn), 773917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul dataAddress); 774917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 775917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(lastAddress); 776917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(fillArrayDataInsn); 777917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 778917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutputSuffix(new OddSpacer(pos)); 779917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutputSuffix(dataAddress); 780917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutputSuffix(dataInsn); 781917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 782917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 783917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 784917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds to the output. 785917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 786917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} instruction to add 787917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 788917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected void addOutput(DalvInsn insn) { 789917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.add(insn); 790917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 791917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 792917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 793917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds to the output suffix. 794917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 795917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} instruction to add 796917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 797917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected void addOutputSuffix(DalvInsn insn) { 798917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul output.addSuffix(insn); 799917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 800917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 801917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 802917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 803917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Instruction visitor class for doing instruction translation with 804917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * local variable tracking 805917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 806917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private class LocalVariableAwareTranslationVisitor 807917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul extends TranslationVisitor { 808917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} local variable info */ 809917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private LocalVariableInfo locals; 810917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 811917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 812917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 813917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 814917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param output {@code non-null;} destination for instruction output 815917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param locals {@code non-null;} the local variable info 816917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 817917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public LocalVariableAwareTranslationVisitor(OutputCollector output, 818917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalVariableInfo locals) { 819917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(output); 820917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.locals = locals; 821917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 822917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 823917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 824917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 825917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainInsn(PlainInsn insn) { 826917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super.visitPlainInsn(insn); 827917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addIntroductionIfNecessary(insn); 828917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 829917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 830917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 831917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 832917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainCstInsn(PlainCstInsn insn) { 833917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super.visitPlainCstInsn(insn); 834917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addIntroductionIfNecessary(insn); 835917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 836917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 837917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 838917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 839917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitSwitchInsn(SwitchInsn insn) { 840917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super.visitSwitchInsn(insn); 841917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addIntroductionIfNecessary(insn); 842917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 843917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 844917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 845917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 846917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingCstInsn(ThrowingCstInsn insn) { 847917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super.visitThrowingCstInsn(insn); 848917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addIntroductionIfNecessary(insn); 849917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 850917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 851917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 852917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 853917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingInsn(ThrowingInsn insn) { 854917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super.visitThrowingInsn(insn); 855917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addIntroductionIfNecessary(insn); 856917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 857917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 858917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 859917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds a {@link LocalStart} to the output if the given 860917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instruction in fact introduces a local variable. 861917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 862917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} instruction in question 863917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 864917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addIntroductionIfNecessary(Insn insn) { 865917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = locals.getAssignment(insn); 866917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 867917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec != null) { 868917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul addOutput(new LocalStart(insn.getPosition(), spec)); 869917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 870917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 871917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 872917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 873