1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.rop.code;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstUtf8;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.StdTypeList;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeList;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ToHuman;
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * A register-based instruction. An instruction is the combination of
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * an opcode (which specifies operation and source/result types), a
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * list of actual sources and result registers/values, and additional
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * information.
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic abstract class Insn implements ToHuman {
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} opcode */
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final Rop opcode;
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} source position */
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final SourcePosition position;
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} spec for the result of this instruction, if any */
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final RegisterSpec result;
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} specs for all the sources of this instruction */
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final RegisterSpecList sources;
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance.
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param opcode {@code non-null;} the opcode
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param position {@code non-null;} source position
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param result {@code null-ok;} spec for the result, if any
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param sources {@code non-null;} specs for all the sources
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Insn(Rop opcode, SourcePosition position, RegisterSpec result,
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                RegisterSpecList sources) {
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (opcode == null) {
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("opcode == null");
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (position == null) {
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("position == null");
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (sources == null) {
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("sources == null");
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.opcode = opcode;
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.position = position;
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.result = result;
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.sources = sources;
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@inheritDoc}
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Instances of this class compare by identity. That is,
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code x.equals(y)} is only true if {@code x == y}.
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final boolean equals(Object other) {
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (this == other);
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@inheritDoc}
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * This implementation returns the identity hashcode of this
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instance. This is proper, since instances of this class compare
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * by identity (see {@link #equals}).
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int hashCode() {
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return System.identityHashCode(this);
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toString() {
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return toStringWithInline(getInlineString());
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets a human-oriented (and slightly lossy) string for this instance.
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the human string form
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toHuman() {
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return toHumanWithInline(getInlineString());
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets an "inline" string portion for toHuman(), if available. This
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is the portion that appears after the Rop opcode
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} if non-null, the inline text for toHuman()
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String getInlineString() {
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return null;
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the opcode.
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the opcode
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final Rop getOpcode() {
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return opcode;
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the source position.
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the source position
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final SourcePosition getPosition() {
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return position;
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the result spec, if any. A return value of {@code null}
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * means this instruction returns nothing.
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the result spec, if any
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final RegisterSpec getResult() {
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the spec of a local variable assignment that occurs at this
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instruction, or null if no local variable assignment occurs. This
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * may be the result register, or for {@code mark-local} insns
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * it may be the source.
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} a named register spec or null
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final RegisterSpec getLocalAssignment() {
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpec assignment;
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (opcode.getOpcode() == RegOps.MARK_LOCAL) {
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            assignment = sources.get(0);
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            assignment = result;
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (assignment == null) {
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        LocalItem localItem = assignment.getLocalItem();
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (localItem == null) {
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return assignment;
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the source specs.
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the source specs
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final RegisterSpecList getSources() {
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sources;
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets whether this instruction can possibly throw an exception. This
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is just a convenient wrapper for {@code getOpcode().canThrow()}.
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code true} iff this instruction can possibly throw
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final boolean canThrow() {
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return opcode.canThrow();
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the list of possibly-caught exceptions. This returns {@link
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * StdTypeList#EMPTY} if this instruction has no handlers,
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * which can be <i>either</i> if this instruction can't possibly
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * throw or if it merely doesn't handle any of its possible
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * exceptions. To determine whether this instruction can throw,
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * use {@link #canThrow}.
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the catches list
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract TypeList getCatches();
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Calls the appropriate method on the given visitor, depending on the
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * class of this instance. Subclasses must override this.
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param visitor {@code non-null;} the visitor to call on
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract void accept(Visitor visitor);
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is just like this one, except that it
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * has a catch list with the given item appended to the end. This
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * method throws an exception if this instance can't possibly
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * throw. To determine whether this instruction can throw, use
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@link #canThrow}.
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} type to append to the catch list
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract Insn withAddedCatch(Type type);
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is just like this one, except that all
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * register references have been offset by the given delta.
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param delta the amount to offset register references by
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract Insn withRegisterOffset(int delta);
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is just like this one, except that, if
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * possible, the insn is converted into a version in which the last
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * source (if it is a constant) is represented directly rather than
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * as a register reference. {@code this} is returned in cases where
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the translation is not possible.
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Insn withLastSourceLiteral() {
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return this;
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an exact copy of this Insn
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Insn copy() {
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return withRegisterOffset(0);
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Compares, handling nulls safely
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param a first object
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param b second object
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return true if they're equal or both null.
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static boolean equalsHandleNulls (Object a, Object b) {
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (a == b) || ((a != null) && a.equals(b));
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Compares Insn contents, since {@code Insn.equals()} is defined
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * to be an identity compare. Insn's are {@code contentEquals()}
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * if they have the same opcode, registers, source position, and other
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * metadata.
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return true in the case described above
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean contentEquals(Insn b) {
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return opcode == b.getOpcode()
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                && position.equals(b.getPosition())
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                && (getClass() == b.getClass())
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                && equalsHandleNulls(result, b.getResult())
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                && equalsHandleNulls(sources, b.getSources())
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                && StdTypeList.equalContents(getCatches(), b.getCatches());
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is just like this one, except
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * with new result and source registers.
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param result {@code null-ok;} new result register
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param sources {@code non-null;} new sources registers
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public abstract Insn withNewRegisters(RegisterSpec result,
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpecList sources);
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the string form of this instance, with the given bit added in
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the standard location for an inline argument.
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param extra {@code null-ok;} the inline argument string
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the string form
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected final String toStringWithInline(String extra) {
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuffer sb = new StringBuffer(80);
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append("Insn{");
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(position);
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(' ');
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(opcode);
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (extra != null) {
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(' ');
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(extra);
318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(" :: ");
321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (result != null) {
323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(result);
324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(" <- ");
325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(sources);
328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append('}');
329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the human string form of this instance, with the given
335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * bit added in the standard location for an inline argument.
336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param extra {@code null-ok;} the inline argument string
338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the human string form
339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    protected final String toHumanWithInline(String extra) {
341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuffer sb = new StringBuffer(80);
342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(position);
344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(": ");
345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(opcode.getNickname());
346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (extra != null) {
348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append("(");
349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(extra);
350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(")");
351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (result == null) {
354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(" .");
355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(" ");
357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(result.toHuman());
358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(" <-");
361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int sz = sources.size();
363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (sz == 0) {
364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(" .");
365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (int i = 0; i < sz; i++) {
367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(" ");
368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(sources.get(i).toHuman());
369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Visitor interface for this (outer) class.
378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static interface Visitor {
380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Visits a {@link PlainInsn}.
382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param insn {@code non-null;} the instruction to visit
384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitPlainInsn(PlainInsn insn);
386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Visits a {@link PlainCstInsn}.
389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param insn {@code non-null;} the instruction to visit
391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitPlainCstInsn(PlainCstInsn insn);
393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Visits a {@link SwitchInsn}.
396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param insn {@code non-null;} the instruction to visit
398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitSwitchInsn(SwitchInsn insn);
400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Visits a {@link ThrowingCstInsn}.
403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param insn {@code non-null;} the instruction to visit
405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitThrowingCstInsn(ThrowingCstInsn insn);
407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Visits a {@link ThrowingInsn}.
410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param insn {@code non-null;} the instruction to visit
412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitThrowingInsn(ThrowingInsn insn);
414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Visits a {@link FillArrayDataInsn}.
417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param insn {@code non-null;} the instruction to visit
419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitFillArrayDataInsn(FillArrayDataInsn insn);
421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Base implementation of {@link Visitor}, which has empty method
425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * bodies for all methods.
426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static class BaseVisitor implements Visitor {
428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitPlainInsn(PlainInsn insn) {
430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This space intentionally left blank.
431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitPlainCstInsn(PlainCstInsn insn) {
435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This space intentionally left blank.
436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitSwitchInsn(SwitchInsn insn) {
440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This space intentionally left blank.
441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitThrowingCstInsn(ThrowingCstInsn insn) {
445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This space intentionally left blank.
446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitThrowingInsn(ThrowingInsn insn) {
450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This space intentionally left blank.
451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void visitFillArrayDataInsn(FillArrayDataInsn insn) {
455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // This space intentionally left blank.
456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
459