1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.rop.code;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.StdTypeList;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type;
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.TypeList;
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Hex;
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Class that describes all the immutable parts of register-based operations.
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class Rop {
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** minimum {@code BRANCH_*} value */
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_MIN = 1;
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indicates a non-branching op */
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_NONE = 1;
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indicates a function/method return */
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_RETURN = 2;
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indicates an unconditional goto */
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_GOTO = 3;
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indicates a two-way branch */
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_IF = 4;
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indicates a switch-style branch */
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_SWITCH = 5;
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indicates a throw-style branch (both always-throws and may-throw) */
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_THROW = 6;
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** maximum {@code BRANCH_*} value */
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static final int BRANCH_MAX = 6;
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** the opcode; one of the constants in {@link RegOps} */
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final int opcode;
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code non-null;} result type of this operation; {@link Type#VOID} for
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * no-result operations
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final Type result;
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} types of all the sources of this operation */
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final TypeList sources;
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} list of possible types thrown by this operation */
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final TypeList exceptions;
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * the branchingness of this op; one of the {@code BRANCH_*}
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * constants in this class
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final int branchingness;
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** whether this is a function/method call op or similar */
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final boolean isCallLike;
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code null-ok;} nickname, if specified (used for debugging) */
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final String nickname;
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an instance. This method is private. Use one of the
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * public constructors.
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param opcode the opcode; one of the constants in {@link RegOps}
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param result {@code non-null;} result type of this operation; {@link
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Type#VOID} for no-result operations
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sources {@code non-null;} types of all the sources of this operation
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param exceptions {@code non-null;} list of possible types thrown by this
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * operation
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param branchingness the branchingness of this op; one of the
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code BRANCH_*} constants
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param isCallLike whether the op is a function/method call or similar
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param nickname {@code null-ok;} optional nickname (used for debugging)
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Rop(int opcode, Type result, TypeList sources,
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson               TypeList exceptions, int branchingness, boolean isCallLike,
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson               String nickname) {
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (result == null) {
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("result == null");
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (sources == null) {
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("sources == null");
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (exceptions == null) {
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new NullPointerException("exceptions == null");
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if ((branchingness < BRANCH_MIN) || (branchingness > BRANCH_MAX)) {
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("bogus branchingness");
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if ((exceptions.size() != 0) && (branchingness != BRANCH_THROW)) {
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("exceptions / branchingness " +
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                               "mismatch");
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.opcode = opcode;
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.result = result;
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.sources = sources;
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.exceptions = exceptions;
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.branchingness = branchingness;
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.isCallLike = isCallLike;
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.nickname = nickname;
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an instance. The constructed instance is never a
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * call-like op (see {@link #isCallLike}).
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param opcode the opcode; one of the constants in {@link RegOps}
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param result {@code non-null;} result type of this operation; {@link
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Type#VOID} for no-result operations
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sources {@code non-null;} types of all the sources of this operation
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param exceptions {@code non-null;} list of possible types thrown by this
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * operation
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param branchingness the branchingness of this op; one of the
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code BRANCH_*} constants
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param nickname {@code null-ok;} optional nickname (used for debugging)
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Rop(int opcode, Type result, TypeList sources,
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson               TypeList exceptions, int branchingness, String nickname) {
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this(opcode, result, sources, exceptions, branchingness, false,
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             nickname);
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs a no-exception instance. The constructed instance is never a
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * call-like op (see {@link #isCallLike}).
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param opcode the opcode; one of the constants in {@link RegOps}
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param result {@code non-null;} result type of this operation; {@link
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Type#VOID} for no-result operations
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sources {@code non-null;} types of all the sources of this operation
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param branchingness the branchingness of this op; one of the
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code BRANCH_*} constants
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param nickname {@code null-ok;} optional nickname (used for debugging)
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Rop(int opcode, Type result, TypeList sources, int branchingness,
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson               String nickname) {
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this(opcode, result, sources, StdTypeList.EMPTY, branchingness, false,
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             nickname);
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs a non-branching no-exception instance. The
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code branchingness} is always {@code BRANCH_NONE},
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * and it is never a call-like op (see {@link #isCallLike}).
169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param opcode the opcode; one of the constants in {@link RegOps}
171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param result {@code non-null;} result type of this operation; {@link
172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Type#VOID} for no-result operations
173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sources {@code non-null;} types of all the sources of this operation
174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param nickname {@code null-ok;} optional nickname (used for debugging)
175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Rop(int opcode, Type result, TypeList sources, String nickname) {
177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this(opcode, result, sources, StdTypeList.EMPTY, Rop.BRANCH_NONE,
178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             false, nickname);
179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs a non-empty exceptions instance. Its
183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code branchingness} is always {@code BRANCH_THROW},
184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * but it is never a call-like op (see {@link #isCallLike}).
185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param opcode the opcode; one of the constants in {@link RegOps}
187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param result {@code non-null;} result type of this operation; {@link
188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Type#VOID} for no-result operations
189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sources {@code non-null;} types of all the sources of this operation
190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param exceptions {@code non-null;} list of possible types thrown by this
191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * operation
192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param nickname {@code null-ok;} optional nickname (used for debugging)
193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Rop(int opcode, Type result, TypeList sources, TypeList exceptions,
195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson               String nickname) {
196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this(opcode, result, sources, exceptions, Rop.BRANCH_THROW, false,
197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             nickname);
198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs a non-nicknamed instance with non-empty exceptions, which
202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * is always a call-like op (see {@link #isCallLike}). Its
203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code branchingness} is always {@code BRANCH_THROW}.
204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param opcode the opcode; one of the constants in {@link RegOps}
206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param sources {@code non-null;} types of all the sources of this operation
207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param exceptions {@code non-null;} list of possible types thrown by this
208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * operation
209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Rop(int opcode, TypeList sources, TypeList exceptions) {
211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this(opcode, Type.VOID, sources, exceptions, Rop.BRANCH_THROW, true,
212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             null);
213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean equals(Object other) {
218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (this == other) {
219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Easy out.
220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return true;
221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (!(other instanceof Rop)) {
224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return false;
225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Rop rop = (Rop) other;
228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (opcode == rop.opcode) &&
230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (branchingness == rop.branchingness) &&
231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            (result == rop.result) &&
232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sources.equals(rop.sources) &&
233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            exceptions.equals(rop.exceptions);
234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int hashCode() {
239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int h = (opcode * 31) + branchingness;
240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        h = (h * 31) + result.hashCode();
241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        h = (h * 31) + sources.hashCode();
242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        h = (h * 31) + exceptions.hashCode();
243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return h;
245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toString() {
250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        StringBuffer sb = new StringBuffer(40);
251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        sb.append("Rop{");
253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        sb.append(RegOps.opName(opcode));
255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (result != Type.VOID) {
257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(" ");
258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(result);
259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(" .");
261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        sb.append(" <-");
264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int sz = sources.size();
266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (sz == 0) {
267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(" .");
268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (int i = 0; i < sz; i++) {
270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                sb.append(' ');
271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                sb.append(sources.getType(i));
272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (isCallLike) {
276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(" call");
277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        sz = exceptions.size();
280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (sz != 0) {
281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(" throws");
282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (int i = 0; i < sz; i++) {
283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                sb.append(' ');
284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                Type one = exceptions.getType(i);
285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (one == Type.THROWABLE) {
286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    sb.append("<any>");
287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                } else {
288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    sb.append(exceptions.getType(i));
289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            switch (branchingness) {
293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case BRANCH_NONE:   sb.append(" flows"); break;
294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case BRANCH_RETURN: sb.append(" returns"); break;
295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case BRANCH_GOTO:   sb.append(" gotos"); break;
296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case BRANCH_IF:     sb.append(" ifs"); break;
297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                case BRANCH_SWITCH: sb.append(" switches"); break;
298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                default: sb.append(" " + Hex.u1(branchingness)); break;
299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        sb.append('}');
303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return sb.toString();
305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the opcode.
309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return the opcode
311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getOpcode() {
313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return opcode;
314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the result type. A return value of {@link Type#VOID}
318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * means this operation returns nothing.
319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code null-ok;} the result spec
321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public Type getResult() {
323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return result;
324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the source types.
328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the source types
330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public TypeList getSources() {
332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return sources;
333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the list of exception types that might be thrown.
337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the list of exception types
339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public TypeList getExceptions() {
341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return exceptions;
342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the branchingness of this instance.
346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return the branchingness
348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int getBranchingness() {
350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return branchingness;
351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this opcode is a function/method call or similar.
355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code true} iff this opcode is call-like
357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isCallLike() {
359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return isCallLike;
360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this opcode is commutative (the order of its sources are
365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * unimportant) or not. All commutative Rops have exactly two sources and
366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * have no branchiness.
367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return true if rop is commutative
369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean isCommutative() {
371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (opcode) {
372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.AND:
373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.OR:
374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.XOR:
375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.ADD:
376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.MUL:
377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return true;
378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            default:
379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return false;
380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the nickname. If this instance has no nickname, this returns
385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * the result of calling {@link #toString}.
386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the nickname
388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String getNickname() {
390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (nickname != null) {
391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return nickname;
392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return toString();
395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets whether this operation can possibly throw an exception. This
399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * is just a convenient wrapper for
400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@code getExceptions().size() != 0}.
401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code true} iff this operation can possibly throw
403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public final boolean canThrow() {
405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return (exceptions.size() != 0);
406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
408