1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.cf.direct;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.code.ByteOps;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.code.BytecodeArray;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.code.SwitchList;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.cf.iface.ParseObserver;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstDouble;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFloat;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstKnownNull;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLong;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ByteArray;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.IntList;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Bytecode visitor to use when "observing" bytecode getting parsed.
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class CodeObserver implements BytecodeArray.Visitor {
4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} actual array of bytecode */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ByteArray bytes;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} observer to inform of parsing */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ParseObserver observer;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param bytes {@code non-null;} actual array of bytecode
5299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param observer {@code non-null;} observer to inform of parsing
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public CodeObserver(ByteArray bytes, ParseObserver observer) {
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (bytes == null) {
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("bytes == null");
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (observer == null) {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("observer == null");
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.bytes = bytes;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.observer = observer;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitInvalid(int opcode, int offset, int length) {
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length, header(offset));
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitNoArgs(int opcode, int offset, int length, Type type) {
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length, header(offset));
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitLocal(int opcode, int offset, int length,
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int idx, Type type, int value) {
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String idxStr = (length <= 3) ? Hex.u1(idx) : Hex.u2(idx);
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean argComment = (length == 1);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String valueStr = "";
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opcode == ByteOps.IINC) {
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = ", #" +
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ((length <= 3) ? Hex.s1(value) : Hex.s2(value));
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String catStr = "";
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type.isCategory2()) {
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catStr = (argComment ? "," : " //") + " category-2";
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + (argComment ? " // " : " ") +
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        idxStr + valueStr + catStr);
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitConstant(int opcode, int offset, int length,
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Constant cst, int value) {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstKnownNull) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // This is aconst_null.
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            visitNoArgs(opcode, offset, length, null);
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstInteger) {
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            visitLiteralInt(opcode, offset, length, value);
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstLong) {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            visitLiteralLong(opcode, offset, length,
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             ((CstLong) cst).getValue());
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstFloat) {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            visitLiteralFloat(opcode, offset, length,
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                              ((CstFloat) cst).getIntBits());
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstDouble) {
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            visitLiteralDouble(opcode, offset, length,
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                             ((CstDouble) cst).getLongBits());
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String valueStr = "";
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (value != 0) {
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = ", ";
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (opcode == ByteOps.MULTIANEWARRAY) {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                valueStr += Hex.u1(value);
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                valueStr += Hex.u2(value);
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + " " + cst + valueStr);
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitBranch(int opcode, int offset, int length,
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            int target) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String targetStr = (length <= 3) ? Hex.u2(target) : Hex.u4(target);
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + " " + targetStr);
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitSwitch(int opcode, int offset, int length,
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SwitchList cases, int padding) {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = cases.size();
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(sz * 20 + 100);
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(header(offset));
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (padding != 0) {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" // padding: " + Hex.u4(padding));
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('\n');
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("  ");
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(Hex.s4(cases.getValue(i)));
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(": ");
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(Hex.u2(cases.getTarget(i)));
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append('\n');
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append("  default: ");
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(Hex.u2(cases.getDefaultTarget()));
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length, sb.toString());
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void visitNewarray(int offset, int length, CstType cst,
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ArrayList<Constant> intVals) {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String commentOrSpace = (length == 1) ? " // " : " ";
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String typeName = cst.getClassType().getComponentType().toHuman();
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + commentOrSpace + typeName);
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void setPreviousOffset(int offset) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Do nothing
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getPreviousOffset() {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return -1;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper to produce the first bit of output for each instruction.
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param offset the offset to the start of the instruction
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private String header(int offset) {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note: This uses the original bytecode, not the
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * possibly-transformed one.
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int opcode = bytes.getUnsignedByte(offset);
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String name = ByteOps.opName(opcode);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opcode == ByteOps.WIDE) {
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            opcode = bytes.getUnsignedByte(offset + 1);
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            name += " " + ByteOps.opName(opcode);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return Hex.u2(offset) + ": " + name;
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
22199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Helper for {@link #visitConstant} where the constant is an
22299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code int}.
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param offset offset to the instruction
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param length instruction length
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value constant value
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void visitLiteralInt(int opcode, int offset, int length,
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int value) {
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String commentOrSpace = (length == 1) ? " // " : " ";
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String valueStr;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        opcode = bytes.getUnsignedByte(offset); // Compare with orig op below.
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((length == 1) || (opcode == ByteOps.BIPUSH)) {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = "#" + Hex.s1(value);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (opcode == ByteOps.SIPUSH) {
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = "#" + Hex.s2(value);
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = "#" + Hex.s4(value);
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + commentOrSpace + valueStr);
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
24899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Helper for {@link #visitConstant} where the constant is a
24999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code long}.
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param offset offset to the instruction
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param length instruction length
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param value constant value
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void visitLiteralLong(int opcode, int offset, int length,
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long value) {
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String commentOrLit = (length == 1) ? " // " : " #";
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String valueStr;
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (length == 1) {
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = Hex.s1((int) value);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            valueStr = Hex.s8(value);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + commentOrLit + valueStr);
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
27299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Helper for {@link #visitConstant} where the constant is a
27399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code float}.
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param offset offset to the instruction
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param length instruction length
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bits constant value, as float-bits
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void visitLiteralFloat(int opcode, int offset, int length,
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int bits) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String optArg = (length != 1) ? " #" + Hex.u4(bits) : "";
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + optArg + " // " +
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        Float.intBitsToFloat(bits));
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
29099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Helper for {@link #visitConstant} where the constant is a
29199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code double}.
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param offset offset to the instruction
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param length instruction length
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bits constant value, as double-bits
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void visitLiteralDouble(int opcode, int offset, int length,
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long bits) {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String optArg = (length != 1) ? " #" + Hex.u8(bits) : "";
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        observer.parsed(bytes, offset, length,
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        header(offset) + optArg + " // " +
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        Double.longBitsToDouble(bits));
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
307