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.rop.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeList;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Class that describes all the immutable parts of register-based operations.
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class Rop {
2899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** minimum {@code BRANCH_*} value */
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_MIN = 1;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indicates a non-branching op */
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_NONE = 1;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indicates a function/method return */
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_RETURN = 2;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indicates an unconditional goto */
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_GOTO = 3;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indicates a two-way branch */
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_IF = 4;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indicates a switch-style branch */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_SWITCH = 5;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** indicates a throw-style branch (both always-throws and may-throw) */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_THROW = 6;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** maximum {@code BRANCH_*} value */
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final int BRANCH_MAX = 6;
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** the opcode; one of the constants in {@link RegOps} */
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int opcode;
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} result type of this operation; {@link Type#VOID} for
57de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * no-result operations
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Type result;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} types of all the sources of this operation */
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final TypeList sources;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} list of possible types thrown by this operation */
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final TypeList exceptions;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
6899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * the branchingness of this op; one of the {@code BRANCH_*}
69de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * constants in this class
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int branchingness;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** whether this is a function/method call op or similar */
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final boolean isCallLike;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} nickname, if specified (used for debugging) */
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final String nickname;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance. This method is private. Use one of the
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * public constructors.
82de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode; one of the constants in {@link RegOps}
8499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result type of this operation; {@link
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Type#VOID} for no-result operations
8699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} types of all the sources of this operation
8799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param exceptions {@code non-null;} list of possible types thrown by this
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * operation
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param branchingness the branchingness of this op; one of the
9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code BRANCH_*} constants
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param isCallLike whether the op is a function/method call or similar
9299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param nickname {@code null-ok;} optional nickname (used for debugging)
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop(int opcode, Type result, TypeList sources,
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               TypeList exceptions, int branchingness, boolean isCallLike,
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               String nickname) {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == null) {
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("result == null");
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sources == null) {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("sources == null");
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (exceptions == null) {
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("exceptions == null");
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((branchingness < BRANCH_MIN) || (branchingness > BRANCH_MAX)) {
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("bogus branchingness");
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((exceptions.size() != 0) && (branchingness != BRANCH_THROW)) {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("exceptions / branchingness " +
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                               "mismatch");
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.opcode = opcode;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.result = result;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.sources = sources;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.exceptions = exceptions;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.branchingness = branchingness;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.isCallLike = isCallLike;
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.nickname = nickname;
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
128de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * Constructs an instance. The constructed instance is never a
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call-like op (see {@link #isCallLike}).
130de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode; one of the constants in {@link RegOps}
13299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result type of this operation; {@link
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Type#VOID} for no-result operations
13499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} types of all the sources of this operation
13599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param exceptions {@code non-null;} list of possible types thrown by this
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * operation
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param branchingness the branchingness of this op; one of the
13899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code BRANCH_*} constants
13999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param nickname {@code null-ok;} optional nickname (used for debugging)
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop(int opcode, Type result, TypeList sources,
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               TypeList exceptions, int branchingness, String nickname) {
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(opcode, result, sources, exceptions, branchingness, false,
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             nickname);
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
148de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * Constructs a no-exception instance. The constructed instance is never a
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call-like op (see {@link #isCallLike}).
150de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode; one of the constants in {@link RegOps}
15299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result type of this operation; {@link
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Type#VOID} for no-result operations
15499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} types of all the sources of this operation
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param branchingness the branchingness of this op; one of the
15699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code BRANCH_*} constants
15799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param nickname {@code null-ok;} optional nickname (used for debugging)
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop(int opcode, Type result, TypeList sources, int branchingness,
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               String nickname) {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(opcode, result, sources, StdTypeList.EMPTY, branchingness, false,
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             nickname);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a non-branching no-exception instance. The
16799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code branchingness} is always {@code BRANCH_NONE},
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and it is never a call-like op (see {@link #isCallLike}).
169de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode; one of the constants in {@link RegOps}
17199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result type of this operation; {@link
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Type#VOID} for no-result operations
17399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} types of all the sources of this operation
17499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param nickname {@code null-ok;} optional nickname (used for debugging)
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop(int opcode, Type result, TypeList sources, String nickname) {
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(opcode, result, sources, StdTypeList.EMPTY, Rop.BRANCH_NONE,
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             false, nickname);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a non-empty exceptions instance. Its
18399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code branchingness} is always {@code BRANCH_THROW},
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * but it is never a call-like op (see {@link #isCallLike}).
185de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode; one of the constants in {@link RegOps}
18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result type of this operation; {@link
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Type#VOID} for no-result operations
18999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} types of all the sources of this operation
19099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param exceptions {@code non-null;} list of possible types thrown by this
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * operation
19299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param nickname {@code null-ok;} optional nickname (used for debugging)
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop(int opcode, Type result, TypeList sources, TypeList exceptions,
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               String nickname) {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(opcode, result, sources, exceptions, Rop.BRANCH_THROW, false,
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             nickname);
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a non-nicknamed instance with non-empty exceptions, which
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is always a call-like op (see {@link #isCallLike}). Its
20399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code branchingness} is always {@code BRANCH_THROW}.
204de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode; one of the constants in {@link RegOps}
20699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param sources {@code non-null;} types of all the sources of this operation
20799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param exceptions {@code non-null;} list of possible types thrown by this
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * operation
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop(int opcode, TypeList sources, TypeList exceptions) {
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(opcode, Type.VOID, sources, exceptions, Rop.BRANCH_THROW, true,
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             null);
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean equals(Object other) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this == other) {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Easy out.
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(other instanceof Rop)) {
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Rop rop = (Rop) other;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (opcode == rop.opcode) &&
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (branchingness == rop.branchingness) &&
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (result == rop.result) &&
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources.equals(rop.sources) &&
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            exceptions.equals(rop.exceptions);
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int hashCode() {
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int h = (opcode * 31) + branchingness;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        h = (h * 31) + result.hashCode();
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        h = (h * 31) + sources.hashCode();
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        h = (h * 31) + exceptions.hashCode();
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return h;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(40);
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append("Rop{");
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(RegOps.opName(opcode));
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result != Type.VOID) {
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" ");
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(result);
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" .");
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(" <-");
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = sources.size();
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sz == 0) {
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" .");
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sz; i++) {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(' ');
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(sources.getType(i));
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (isCallLike) {
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" call");
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sz = exceptions.size();
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sz != 0) {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" throws");
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sz; i++) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(' ');
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Type one = exceptions.getType(i);
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (one == Type.THROWABLE) {
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sb.append("<any>");
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sb.append(exceptions.getType(i));
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (branchingness) {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case BRANCH_NONE:   sb.append(" flows"); break;
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case BRANCH_RETURN: sb.append(" returns"); break;
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case BRANCH_GOTO:   sb.append(" gotos"); break;
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case BRANCH_IF:     sb.append(" ifs"); break;
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case BRANCH_SWITCH: sb.append(" switches"); break;
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                default: sb.append(" " + Hex.u1(branchingness)); break;
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append('}');
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the opcode.
309de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the opcode
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getOpcode() {
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return opcode;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the result type. A return value of {@link Type#VOID}
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * means this operation returns nothing.
319de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
32099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the result spec
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Type getResult() {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the source types.
328de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
32999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the source types
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeList getSources() {
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sources;
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the list of exception types that might be thrown.
337de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
33899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the list of exception types
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeList getExceptions() {
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return exceptions;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the branchingness of this instance.
346de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the branchingness
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getBranchingness() {
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return branchingness;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether this opcode is a function/method call or similar.
355de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
35699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff this opcode is call-like
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean isCallLike() {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return isCallLike;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether this opcode is commutative (the order of its sources are
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * unimportant) or not. All commutative Rops have exactly two sources and
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have no branchiness.
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return true if rop is commutative
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean isCommutative() {
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (opcode) {
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case RegOps.AND:
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case RegOps.OR:
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case RegOps.XOR:
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case RegOps.ADD:
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case RegOps.MUL:
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return true;
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the nickname. If this instance has no nickname, this returns
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the result of calling {@link #toString}.
386de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
38799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the nickname
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String getNickname() {
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (nickname != null) {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return nickname;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return toString();
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether this operation can possibly throw an exception. This
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is just a convenient wrapper for
40099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code getExceptions().size() != 0}.
401de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
40299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code true} iff this operation can possibly throw
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final boolean canThrow() {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (exceptions.size() != 0);
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
408