PreInstructionRegisterInfoMethodItem.java revision ffe82bdcb5c914b3a60b630c6d3abe6fc9229dec
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2010 Ben Gruver
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.jf.baksmali.Adaptors;
30
31//TODO: uncomment
32/*public class PreInstructionRegisterInfoMethodItem extends MethodItem {
33    private final AnalyzedInstruction analyzedInstruction;
34    private final MethodAnalyzer methodAnalyzer;
35
36    public PreInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer,
37                                                int codeAddress) {
38        super(codeAddress);
39        this.analyzedInstruction = analyzedInstruction;
40        this.methodAnalyzer = methodAnalyzer;
41    }
42
43    @Override
44    public double getSortOrder() {
45        return 99.9;
46    }
47
48    @Override
49    public boolean writeTo(IndentingWriter writer) throws IOException {
50        int registerInfo = baksmali.registerInfo;
51        int registerCount = analyzedInstruction.getRegisterCount();
52        BitSet registers = new BitSet(registerCount);
53
54        if ((registerInfo & main.ALL) != 0) {
55            registers.set(0, registerCount);
56        } else {
57            if ((registerInfo & main.ALLPRE) != 0) {
58                registers.set(0, registerCount);
59            } else {
60                if ((registerInfo & main.ARGS) != 0) {
61                    addArgsRegs(registers);
62                }
63                if ((registerInfo & main.MERGE) != 0) {
64                    addMergeRegs(registers, registerCount);
65                } else if ((registerInfo & main.FULLMERGE) != 0 &&
66                        (analyzedInstruction.isBeginningInstruction())) {
67                    addParamRegs(registers, registerCount);
68                }
69            }
70        }
71
72        boolean printedSomething = false;
73        if ((registerInfo & main.FULLMERGE) != 0) {
74            printedSomething = writeFullMergeRegs(writer, registers, registerCount);
75        }
76
77        printedSomething |= writeRegisterInfo(writer, registers, printedSomething);
78
79        return printedSomething;
80    }
81
82    private void addArgsRegs(BitSet registers) {
83        if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) {
84            RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction();
85
86            registers.set(instruction.getStartRegister(),
87                    instruction.getStartRegister() + instruction.getRegCount());
88        } else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
89            FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction();
90            int regCount = instruction.getRegCount();
91            switch (regCount) {
92                case 5:
93                    registers.set(instruction.getRegisterA());
94                    //fall through
95                case 4:
96                    registers.set(instruction.getRegisterG());
97                    //fall through
98                case 3:
99                    registers.set(instruction.getRegisterF());
100                    //fall through
101                case 2:
102                    registers.set(instruction.getRegisterE());
103                    //fall through
104                case 1:
105                    registers.set(instruction.getRegisterD());
106            }
107        } else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
108            ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction();
109            registers.set(instruction.getRegisterA());
110            registers.set(instruction.getRegisterB());
111            registers.set(instruction.getRegisterC());
112        } else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) {
113            TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction();
114            registers.set(instruction.getRegisterA());
115            registers.set(instruction.getRegisterB());
116        } else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) {
117            SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction();
118            registers.set(instruction.getRegisterA());
119        }
120    }
121
122    private void addMergeRegs(BitSet registers, int registerCount) {
123        if (analyzedInstruction.isBeginningInstruction()) {
124            addParamRegs(registers, registerCount);
125        }
126
127        if (analyzedInstruction.getPredecessorCount() <= 1) {
128            //in the common case of an instruction that only has a single predecessor which is the previous
129            //instruction, the pre-instruction registers will always match the previous instruction's
130            //post-instruction registers
131            return;
132        }
133
134        for (int registerNum=0; registerNum<registerCount; registerNum++) {
135            RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
136
137            for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
138                if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
139                    registers.set(registerNum);
140                    continue;
141                }
142            }
143        }
144    }
145
146    private void addParamRegs(BitSet registers, int registerCount) {
147        ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
148        int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount();
149        if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
150            parameterRegisterCount++;
151        }
152
153        registers.set(registerCount-parameterRegisterCount, registerCount);
154    }
155
156    private boolean writeFullMergeRegs(IndentingWriter writer, BitSet registers, int registerCount)
157                                    throws IOException {
158        if (analyzedInstruction.getPredecessorCount() <= 1) {
159            return false;
160        }
161
162        ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
163
164        boolean firstRegister = true;
165
166        for (int registerNum=0; registerNum<registerCount; registerNum++) {
167            RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
168            boolean addRegister = false;
169
170            for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
171                RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
172                if (predecessorRegisterType.category != RegisterType.Category.Unknown &&
173                        predecessorRegisterType != mergedRegisterType) {
174
175                    addRegister = true;
176                    break;
177                }
178            }
179
180            if (!addRegister) {
181                continue;
182            }
183
184            if (firstRegister) {
185                firstRegister = false;
186            } else {
187                writer.write('\n');
188            }
189
190            writer.write('#');
191            RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
192            writer.write('=');
193            analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer);
194            writer.write(":merge{");
195
196            boolean first = true;
197
198            for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) {
199                RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
200
201                if (!first) {
202                    writer.write(',');
203                }
204
205                if (predecessor.getInstructionIndex() == -1) {
206                    //the fake "StartOfMethod" instruction
207                    writer.write("Start:");
208                } else {
209                    writer.write("0x");
210                    writer.printUnsignedLongAsHex(methodAnalyzer.getInstructionAddress(predecessor));
211                    writer.write(':');
212                }
213                predecessorRegisterType.writeTo(writer);
214
215                first = false;
216            }
217            writer.write('}');
218
219            registers.clear(registerNum);
220        }
221        return !firstRegister;
222    }
223
224    private boolean writeRegisterInfo(IndentingWriter writer, BitSet registers,
225                                      boolean addNewline) throws IOException {
226        ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod();
227
228        int registerNum = registers.nextSetBit(0);
229        if (registerNum < 0) {
230            return false;
231        }
232
233        if (addNewline) {
234            writer.write('\n');
235        }
236        writer.write('#');
237        for (; registerNum >= 0; registerNum = registers.nextSetBit(registerNum + 1)) {
238
239            RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum);
240
241            RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum);
242            writer.write('=');
243
244            if (registerType == null) {
245                writer.write("null");
246            } else {
247                registerType.writeTo(writer);
248            }
249            writer.write(';');
250        }
251        return true;
252    }
253}*/
254