CstInsn.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.dx.dex.code;
18
19import com.android.dx.rop.code.RegisterSpecList;
20import com.android.dx.rop.code.SourcePosition;
21import com.android.dx.rop.cst.Constant;
22
23/**
24 * Instruction which has a single constant argument in addition
25 * to all the normal instruction information.
26 */
27public final class CstInsn extends FixedSizeInsn {
28    /** {@code non-null;} the constant argument for this instruction */
29    private final Constant constant;
30
31    /**
32     * {@code >= -1;} the constant pool index for {@link #constant}, or
33     * {@code -1} if not yet set
34     */
35    private int index;
36
37    /**
38     * {@code >= -1;} the constant pool index for the class reference in
39     * {@link #constant} if any, or {@code -1} if not yet set
40     */
41    private int classIndex;
42
43    /**
44     * Constructs an instance. The output address of this instance is
45     * initially unknown ({@code -1}) as is the constant pool index.
46     *
47     * @param opcode the opcode; one of the constants from {@link Dops}
48     * @param position {@code non-null;} source position
49     * @param registers {@code non-null;} register list, including a
50     * result register if appropriate (that is, registers may be either
51     * ins or outs)
52     * @param constant {@code non-null;} constant argument
53     */
54    public CstInsn(Dop opcode, SourcePosition position,
55                   RegisterSpecList registers, Constant constant) {
56        super(opcode, position, registers);
57
58        if (constant == null) {
59            throw new NullPointerException("constant == null");
60        }
61
62        this.constant = constant;
63        this.index = -1;
64        this.classIndex = -1;
65    }
66
67    /** {@inheritDoc} */
68    @Override
69    public DalvInsn withOpcode(Dop opcode) {
70        CstInsn result =
71            new CstInsn(opcode, getPosition(), getRegisters(), constant);
72
73        if (index >= 0) {
74            result.setIndex(index);
75        }
76
77        if (classIndex >= 0) {
78            result.setClassIndex(classIndex);
79        }
80
81        return result;
82    }
83
84    /** {@inheritDoc} */
85    @Override
86    public DalvInsn withRegisters(RegisterSpecList registers) {
87        CstInsn result =
88            new CstInsn(getOpcode(), getPosition(), registers, constant);
89
90        if (index >= 0) {
91            result.setIndex(index);
92        }
93
94        if (classIndex >= 0) {
95            result.setClassIndex(classIndex);
96        }
97
98        return result;
99    }
100
101    /**
102     * Gets the constant argument.
103     *
104     * @return {@code non-null;} the constant argument
105     */
106    public Constant getConstant() {
107        return constant;
108    }
109
110    /**
111     * Gets the constant's index. It is only valid to call this after
112     * {@link #setIndex} has been called.
113     *
114     * @return {@code >= 0;} the constant pool index
115     */
116    public int getIndex() {
117        if (index < 0) {
118            throw new RuntimeException("index not yet set for " + constant);
119        }
120
121        return index;
122    }
123
124    /**
125     * Returns whether the constant's index has been set for this instance.
126     *
127     * @see #setIndex
128     *
129     * @return {@code true} iff the index has been set
130     */
131    public boolean hasIndex() {
132        return (index >= 0);
133    }
134
135    /**
136     * Sets the constant's index. It is only valid to call this method once
137     * per instance.
138     *
139     * @param index {@code >= 0;} the constant pool index
140     */
141    public void setIndex(int index) {
142        if (index < 0) {
143            throw new IllegalArgumentException("index < 0");
144        }
145
146        if (this.index >= 0) {
147            throw new RuntimeException("index already set");
148        }
149
150        this.index = index;
151    }
152
153    /**
154     * Gets the constant's class index. It is only valid to call this after
155     * {@link #setClassIndex} has been called.
156     *
157     * @return {@code >= 0;} the constant's class's constant pool index
158     */
159    public int getClassIndex() {
160        if (classIndex < 0) {
161            throw new RuntimeException("class index not yet set");
162        }
163
164        return classIndex;
165    }
166
167    /**
168     * Returns whether the constant's class index has been set for this
169     * instance.
170     *
171     * @see #setClassIndex
172     *
173     * @return {@code true} iff the index has been set
174     */
175    public boolean hasClassIndex() {
176        return (classIndex >= 0);
177    }
178
179    /**
180     * Sets the constant's class index. This is the constant pool index
181     * for the class referred to by this instance's constant. Only
182     * reference constants have a class, so it is only on instances
183     * with reference constants that this method should ever be
184     * called. It is only valid to call this method once per instance.
185     *
186     * @param index {@code >= 0;} the constant's class's constant pool index
187     */
188    public void setClassIndex(int index) {
189        if (index < 0) {
190            throw new IllegalArgumentException("index < 0");
191        }
192
193        if (this.classIndex >= 0) {
194            throw new RuntimeException("class index already set");
195        }
196
197        this.classIndex = index;
198    }
199
200    /** {@inheritDoc} */
201    @Override
202    protected String argString() {
203        return constant.toHuman();
204    }
205}
206