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.cf.code;
18
19import com.android.dx.rop.cst.CstType;
20import com.android.dx.rop.type.Prototype;
21import com.android.dx.rop.type.Type;
22import com.android.dx.rop.type.TypeBearer;
23import com.android.dx.util.Hex;
24
25/**
26 * {@link Machine} which keeps track of known values but does not do
27 * smart/realistic reference type calculations.
28 */
29public class ValueAwareMachine extends BaseMachine {
30    /**
31     * Constructs an instance.
32     *
33     * @param prototype {@code non-null;} the prototype for the associated
34     * method
35     */
36    public ValueAwareMachine(Prototype prototype) {
37        super(prototype);
38    }
39
40    /** {@inheritDoc} */
41    public void run(Frame frame, int offset, int opcode) {
42        switch (opcode) {
43            case ByteOps.NOP:
44            case ByteOps.IASTORE:
45            case ByteOps.POP:
46            case ByteOps.POP2:
47            case ByteOps.IFEQ:
48            case ByteOps.IFNE:
49            case ByteOps.IFLT:
50            case ByteOps.IFGE:
51            case ByteOps.IFGT:
52            case ByteOps.IFLE:
53            case ByteOps.IF_ICMPEQ:
54            case ByteOps.IF_ICMPNE:
55            case ByteOps.IF_ICMPLT:
56            case ByteOps.IF_ICMPGE:
57            case ByteOps.IF_ICMPGT:
58            case ByteOps.IF_ICMPLE:
59            case ByteOps.IF_ACMPEQ:
60            case ByteOps.IF_ACMPNE:
61            case ByteOps.GOTO:
62            case ByteOps.RET:
63            case ByteOps.LOOKUPSWITCH:
64            case ByteOps.IRETURN:
65            case ByteOps.RETURN:
66            case ByteOps.PUTSTATIC:
67            case ByteOps.PUTFIELD:
68            case ByteOps.ATHROW:
69            case ByteOps.MONITORENTER:
70            case ByteOps.MONITOREXIT:
71            case ByteOps.IFNULL:
72            case ByteOps.IFNONNULL: {
73                // Nothing to do for these ops in this class.
74                clearResult();
75                break;
76            }
77            case ByteOps.LDC:
78            case ByteOps.LDC2_W: {
79                setResult((TypeBearer) getAuxCst());
80                break;
81            }
82            case ByteOps.ILOAD:
83            case ByteOps.ISTORE: {
84                setResult(arg(0));
85                break;
86            }
87            case ByteOps.IALOAD:
88            case ByteOps.IADD:
89            case ByteOps.ISUB:
90            case ByteOps.IMUL:
91            case ByteOps.IDIV:
92            case ByteOps.IREM:
93            case ByteOps.INEG:
94            case ByteOps.ISHL:
95            case ByteOps.ISHR:
96            case ByteOps.IUSHR:
97            case ByteOps.IAND:
98            case ByteOps.IOR:
99            case ByteOps.IXOR:
100            case ByteOps.IINC:
101            case ByteOps.I2L:
102            case ByteOps.I2F:
103            case ByteOps.I2D:
104            case ByteOps.L2I:
105            case ByteOps.L2F:
106            case ByteOps.L2D:
107            case ByteOps.F2I:
108            case ByteOps.F2L:
109            case ByteOps.F2D:
110            case ByteOps.D2I:
111            case ByteOps.D2L:
112            case ByteOps.D2F:
113            case ByteOps.I2B:
114            case ByteOps.I2C:
115            case ByteOps.I2S:
116            case ByteOps.LCMP:
117            case ByteOps.FCMPL:
118            case ByteOps.FCMPG:
119            case ByteOps.DCMPL:
120            case ByteOps.DCMPG:
121            case ByteOps.ARRAYLENGTH: {
122                setResult(getAuxType());
123                break;
124            }
125            case ByteOps.DUP:
126            case ByteOps.DUP_X1:
127            case ByteOps.DUP_X2:
128            case ByteOps.DUP2:
129            case ByteOps.DUP2_X1:
130            case ByteOps.DUP2_X2:
131            case ByteOps.SWAP: {
132                clearResult();
133                for (int pattern = getAuxInt(); pattern != 0; pattern >>= 4) {
134                    int which = (pattern & 0x0f) - 1;
135                    addResult(arg(which));
136                }
137                break;
138            }
139
140            case ByteOps.JSR: {
141                setResult(new ReturnAddress(getAuxTarget()));
142                break;
143            }
144            case ByteOps.GETSTATIC:
145            case ByteOps.GETFIELD:
146            case ByteOps.INVOKEVIRTUAL:
147            case ByteOps.INVOKESTATIC:
148            case ByteOps.INVOKEINTERFACE: {
149                Type type = ((TypeBearer) getAuxCst()).getType();
150                if (type == Type.VOID) {
151                    clearResult();
152                } else {
153                    setResult(type);
154                }
155                break;
156            }
157            case ByteOps.INVOKESPECIAL: {
158                Type thisType = arg(0).getType();
159                if (thisType.isUninitialized()) {
160                    frame.makeInitialized(thisType);
161                }
162                Type type = ((TypeBearer) getAuxCst()).getType();
163                if (type == Type.VOID) {
164                    clearResult();
165                } else {
166                    setResult(type);
167                }
168                break;
169            }
170            case ByteOps.NEW: {
171                Type type = ((CstType) getAuxCst()).getClassType();
172                setResult(type.asUninitialized(offset));
173                break;
174            }
175            case ByteOps.NEWARRAY:
176            case ByteOps.CHECKCAST:
177            case ByteOps.MULTIANEWARRAY: {
178                Type type = ((CstType) getAuxCst()).getClassType();
179                setResult(type);
180                break;
181            }
182            case ByteOps.ANEWARRAY: {
183                Type type = ((CstType) getAuxCst()).getClassType();
184                setResult(type.getArrayType());
185                break;
186            }
187            case ByteOps.INSTANCEOF: {
188                setResult(Type.INT);
189                break;
190            }
191            default: {
192                throw new RuntimeException("shouldn't happen: " +
193                                           Hex.u1(opcode));
194            }
195        }
196
197        storeResults(frame);
198    }
199}
200