MethodAnalyzer.java revision eac512ae67c994d4332c0421f369e026681ee0d5
1d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.compackage org.jf.dexlib.Code.Analysis;
2d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport org.jf.dexlib.*;
4fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport org.jf.dexlib.Code.*;
5472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction;
6472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.Format;
7fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport org.jf.dexlib.Util.*;
8d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
9fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.comimport java.util.*;
10d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
11d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.compublic class MethodAnalyzer {
12d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    private final ClassDataItem.EncodedMethod encodedMethod;
13d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
14fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private SparseArray<AnalyzedInstruction> instructions;
15fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
16fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private boolean analyzed = false;
17d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
18c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    private BitSet verifiedInstructions;
19c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
20c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    private ValidationException validationException = null;
21300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com
22d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    //This is a dummy instruction that occurs immediately before the first real instruction. We can initialize the
23d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    //register types for this instruction to the parameter types, in order to have them propagate to all of its
24d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    //successors, e.g. the first real instruction, the first instructions in any exception handlers covering the first
25d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    //instruction, etc.
26d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    private AnalyzedInstruction startOfMethod;
27d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
28d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    public MethodAnalyzer(ClassDataItem.EncodedMethod encodedMethod) {
29d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        if (encodedMethod == null) {
30d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            throw new IllegalArgumentException("encodedMethod cannot be null");
31d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
32fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (encodedMethod.codeItem == null || encodedMethod.codeItem.getInstructions().length == 0) {
33d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            throw new IllegalArgumentException("The method has no code");
34d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
35d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        this.encodedMethod = encodedMethod;
36fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
37fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //override AnalyzedInstruction and provide custom implementations of some of the methods, so that we don't
38fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //have to handle the case this special case of instruction being null, in the main class
39fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        startOfMethod = new AnalyzedInstruction(null, -1, encodedMethod.codeItem.getRegisterCount()) {
40fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            public boolean setsRegister() {
41fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                return false;
42fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
43fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
44fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            @Override
45fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            public boolean setsWideRegister() {
46fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                return false;
47fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
48fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
49fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            @Override
50fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            public boolean setsRegister(int registerNumber) {
51fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                return false;
52fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
53fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
54fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            @Override
55fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            public int getDestinationRegister() {
56fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                assert false;
57fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                return -1;
58fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            };
59fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        };
60300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com
617e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        buildInstructionList();
627e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
63c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        verifiedInstructions = new BitSet(instructions.size());
64d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    }
65d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
66d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    public AnalyzedInstruction[] analyze() {
67fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert encodedMethod != null;
68fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert encodedMethod.codeItem != null;
69fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
70fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (analyzed) {
71fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            return makeInstructionArray();
72fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
73fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
74fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        CodeItem codeItem = encodedMethod.codeItem;
75fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        MethodIdItem methodIdItem = encodedMethod.method;
76fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
77fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int totalRegisters = codeItem.getRegisterCount();
78fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount();
79fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
80eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com        int nonParameterRegisters = totalRegisters - parameterRegisters;
81eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com
82fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //if this isn't a static method, determine which register is the "this" register and set the type to the
83fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //current class
84fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
85eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com            nonParameterRegisters--;
86fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            int thisRegister = totalRegisters - parameterRegisters - 1;
87fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
88fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //if this is a constructor, then set the "this" register to an uninitialized reference of the current class
89fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            if ((encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0) {
90fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                //TODO: it would probably make more sense to validate this somewhere else, and just put an assert here. Also, need to do a similar check for static constructor
917e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (!encodedMethod.method.getMethodName().getStringValue().equals("<init>")) {
92fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    throw new ValidationException("The constructor flag can only be used with an <init> method.");
93fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                }
94fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
95fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                setRegisterTypeAndPropagateChanges(startOfMethod, thisRegister,
96c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        RegisterType.getRegisterType(RegisterType.Category.UninitThis,
97fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                            ClassPath.getClassDef(methodIdItem.getContainingClass())));
98fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            } else {
997e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (encodedMethod.method.getMethodName().getStringValue().equals("<init>")) {
100fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    throw new ValidationException("An <init> method must have the \"constructor\" access flag");
101fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                }
102fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
103fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                setRegisterTypeAndPropagateChanges(startOfMethod, thisRegister,
104fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                        RegisterType.getRegisterType(RegisterType.Category.Reference,
105fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                            ClassPath.getClassDef(methodIdItem.getContainingClass())));
106fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
107fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
108fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
109fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        TypeListItem parameters = methodIdItem.getPrototype().getParameters();
110fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (parameters != null) {
111fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType[] parameterTypes = getParameterTypes(parameters, parameterRegisters);
112fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            for (int i=0; i<parameterTypes.length; i++) {
113fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                RegisterType registerType = parameterTypes[i];
114fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                int registerNum = (totalRegisters - parameterRegisters) + i;
115fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                setRegisterTypeAndPropagateChanges(startOfMethod, registerNum, registerType);
116fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
117fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
118fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
119eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com        RegisterType uninit = RegisterType.getRegisterType(RegisterType.Category.Uninit, null);
120eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com        for (int i=0; i<nonParameterRegisters; i++) {
121eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com            setRegisterTypeAndPropagateChanges(startOfMethod, i, uninit);
122eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com        }
123eac512ae67c994d4332c0421f369e026681ee0d5JesusFreke@JesusFreke.com
124c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        BitSet instructionsToAnalyze = new BitSet(verifiedInstructions.size());
125300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com
126300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com        //make sure all of the "first instructions" are marked for processing
127300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com        for (AnalyzedInstruction successor: startOfMethod.successors) {
128c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            instructionsToAnalyze.set(successor.instructionIndex);
129300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com        }
130300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com
131c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        while (!instructionsToAnalyze.isEmpty()) {
132c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            for(int i=instructionsToAnalyze.nextSetBit(0); i>=0; i=instructionsToAnalyze.nextSetBit(i+1)) {
133c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                instructionsToAnalyze.clear(i);
134c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                if (verifiedInstructions.get(i)) {
135c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    continue;
136c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                }
137c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                AnalyzedInstruction instructionToVerify = instructions.valueAt(i);
138c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                try {
139c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    analyzeInstruction(instructionToVerify);
140c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                } catch (ValidationException ex) {
141c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    this.validationException = ex;
142c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    int codeAddress = getInstructionAddress(instructionToVerify);
143c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    ex.setCodeAddress(codeAddress);
144c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    ex.addContext(String.format("opcode: %s", instructionToVerify.instruction.opcode.name));
145c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    ex.addContext(String.format("CodeAddress: %d", codeAddress));
146c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    ex.addContext(String.format("Method: %s", encodedMethod.method.getMethodString()));
147c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    break;
148c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                }
149c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
150c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                verifiedInstructions.set(instructionToVerify.getInstructionIndex());
151c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
152c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                for (AnalyzedInstruction successor: instructionToVerify.successors) {
153c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    instructionsToAnalyze.set(successor.getInstructionIndex());
154c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                }
155c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            }
156c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (validationException != null) {
157c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                break;
158300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com            }
159300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com        }
160300ad56aa3c343a84017ae7a2267dc516b5b6202JesusFreke@JesusFreke.com
161fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        analyzed = true;
162fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return makeInstructionArray();
163fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
164fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
165fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private int getThisRegister() {
166fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0;
167fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
168fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        CodeItem codeItem = encodedMethod.codeItem;
169fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert codeItem != null;
170fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
171fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        MethodIdItem methodIdItem = encodedMethod.method;
172fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert methodIdItem != null;
173fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
174fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int totalRegisters = codeItem.getRegisterCount();
175fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (totalRegisters == 0) {
176fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("A non-static method must have at least 1 register");
177fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
178fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
179fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int parameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount();
180fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
181fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return totalRegisters - parameterRegisters - 1;
182fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
183fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
184fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private boolean isInstanceConstructor() {
185fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0 &&
186fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com               (encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0;
187fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
188fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
189fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private boolean isStaticConstructor() {
190fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return (encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) != 0 &&
191fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com               (encodedMethod.accessFlags & AccessFlags.CONSTRUCTOR.getValue()) != 0;
192fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
193fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1941c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    public AnalyzedInstruction getStartOfMethod() {
1951c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        return startOfMethod;
1961c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    }
1971c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
198fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    public AnalyzedInstruction[] makeInstructionArray() {
199fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        AnalyzedInstruction[] instructionArray = new AnalyzedInstruction[instructions.size()];
200fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        for (int i=0; i<instructions.size(); i++) {
201fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            instructionArray[i] = instructions.valueAt(i);
202fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
203fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return instructionArray;
204fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
205fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
206c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    public ValidationException getValidationException() {
207c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        return validationException;
208c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    }
209c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
210fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private static RegisterType[] getParameterTypes(TypeListItem typeListItem, int parameterRegisterCount) {
211fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert typeListItem != null;
212fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert parameterRegisterCount == typeListItem.getRegisterCount();
213fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
214fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType[] registerTypes = new RegisterType[parameterRegisterCount];
215fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
216fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int registerNum = 0;
217fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        for (TypeIdItem type: typeListItem.getTypes()) {
218fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            if (type.getRegisterCount() == 2) {
219fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                registerTypes[registerNum++] = RegisterType.getWideRegisterTypeForTypeIdItem(type, true);
220fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                registerTypes[registerNum++] = RegisterType.getWideRegisterTypeForTypeIdItem(type, false);
221fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            } else {
222c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                registerTypes[registerNum++] = RegisterType.getRegisterTypeForTypeIdItem(type);
223fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
224fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
225fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
226fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return registerTypes;
227fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
228fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
2291c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    public int getInstructionAddress(AnalyzedInstruction instruction) {
230fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        return instructions.keyAt(instruction.instructionIndex);
231fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
232fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
233fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private void setDestinationRegisterTypeAndPropagateChanges(AnalyzedInstruction analyzedInstruction,
234fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                                                               RegisterType registerType) {
235fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister(),
236fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                registerType);
237fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
238fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
23985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private void setRegisterTypeAndPropagateChanges(AnalyzedInstruction analyzedInstruction, int registerNumber,
240fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                                                RegisterType registerType) {
241fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
242fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        BitSet changedInstructions = new BitSet(instructions.size());
243fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
24485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        boolean changed = analyzedInstruction.setPostRegisterType(registerNumber, registerType);
245fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
2467e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        if (!changed) {
247fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            return;
248fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
249fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
25085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        propagateRegisterToSuccessors(analyzedInstruction, registerNumber, changedInstructions);
251fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
252fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //using a for loop inside the while loop optimizes for the common case of the successors of an instruction
253fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //occurring after the instruction. Any successors that occur prior to the instruction will be picked up on
254fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //the next iteration of the while loop.
255fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //this could also be done recursively, but in large methods it would likely cause very deep recursion,
256fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //which would requires the user to specify a larger stack size. This isn't really a problem, but it is
257fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //slightly annoying.
258fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        while (!changedInstructions.isEmpty()) {
259fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            for (int instructionIndex=changedInstructions.nextSetBit(0);
260fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                     instructionIndex>=0;
2617e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                     instructionIndex=changedInstructions.nextSetBit(instructionIndex+1)) {
262fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
263fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                changedInstructions.clear(instructionIndex);
264fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
265fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                propagateRegisterToSuccessors(instructions.valueAt(instructionIndex), registerNumber,
266fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                        changedInstructions);
267fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
268fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
26985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com
27085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (registerType.category == RegisterType.Category.LongLo) {
27185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            checkWidePair(registerNumber, analyzedInstruction);
27285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            setRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1,
27385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    RegisterType.getRegisterType(RegisterType.Category.LongHi, null));
27485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        } else if (registerType.category == RegisterType.Category.DoubleLo) {
27585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            checkWidePair(registerNumber, analyzedInstruction);
27685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            setRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1,
27785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    RegisterType.getRegisterType(RegisterType.Category.DoubleHi, null));
27885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
279d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    }
280d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
281fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private void propagateRegisterToSuccessors(AnalyzedInstruction instruction, int registerNumber,
282fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                                               BitSet changedInstructions) {
283fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        for (AnalyzedInstruction successor: instruction.successors) {
284fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            if (!successor.setsRegister(registerNumber)) {
285fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                RegisterType registerType = successor.getMergedRegisterTypeFromPredecessors(registerNumber);
286fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
2877e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                //TODO: GROT?
2887e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                /*if (registerType.category == RegisterType.Category.UninitRef && instruction.isInvokeInit()) {
28989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    continue;
2907e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                }*/
29189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
292fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                if (successor.setPostRegisterType(registerNumber, registerType)) {
293fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    changedInstructions.set(successor.instructionIndex);
294c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    verifiedInstructions.clear(successor.instructionIndex);
295fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                }
296fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
297fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
298fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
299fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
300fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
301fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
302d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    private void buildInstructionList() {
303d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        assert encodedMethod != null;
304d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        assert encodedMethod.codeItem != null;
305fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int registerCount = encodedMethod.codeItem.getRegisterCount();
306d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
307d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        Instruction[] insns = encodedMethod.codeItem.getInstructions();
308d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
309fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        instructions = new SparseArray<AnalyzedInstruction>(insns.length);
310d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
311d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //first, create all the instructions and populate the instructionAddresses array
312d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        int currentCodeAddress = 0;
313d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        for (int i=0; i<insns.length; i++) {
314fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            instructions.append(currentCodeAddress, new AnalyzedInstruction(insns[i], i, registerCount));
315fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            assert instructions.indexOfKey(currentCodeAddress) == i;
316d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            currentCodeAddress += insns[i].getSize(currentCodeAddress);
317d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
318d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
319d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //next, populate the exceptionHandlers array. The array item for each instruction that can throw an exception
320d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //and is covered by a try block should be set to a list of the first instructions of each exception handler
321d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //for the try block covering the instruction
322d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        CodeItem.TryItem[] tries = encodedMethod.codeItem.getTries();
323d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        int triesIndex = 0;
324d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        CodeItem.TryItem currentTry = null;
325fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        AnalyzedInstruction[] currentExceptionHandlers = null;
326fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        AnalyzedInstruction[][] exceptionHandlers = new AnalyzedInstruction[insns.length][];
327d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3287e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        if (tries != null) {
3297e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            for (int i=0; i<instructions.size(); i++) {
3307e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                AnalyzedInstruction instruction = instructions.valueAt(i);
3317e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                Opcode instructionOpcode = instruction.instruction.opcode;
332c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                currentCodeAddress = getInstructionAddress(instruction);
333d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3347e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                //check if we have gone past the end of the current try
3357e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (currentTry != null) {
3367e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    if (currentTry.getStartCodeAddress() + currentTry.getTryLength() <= currentCodeAddress) {
3377e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        currentTry = null;
3387e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        triesIndex++;
3397e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    }
340d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                }
341d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3427e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                //check if the next try is applicable yet
3437e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (currentTry == null && triesIndex < tries.length) {
3447e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    CodeItem.TryItem tryItem = tries[triesIndex];
3457e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    if (tryItem.getStartCodeAddress() <= currentCodeAddress) {
3467e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        assert(tryItem.getStartCodeAddress() + tryItem.getTryLength() > currentCodeAddress);
347d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3487e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        currentTry = tryItem;
349d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3507e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        currentExceptionHandlers = buildExceptionHandlerArray(tryItem);
3517e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    }
352d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                }
353d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3547e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                //if we're inside a try block, and the instruction can throw an exception, then add the exception handlers
3557e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                //for the current instruction
3567e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (currentTry != null && instructionOpcode.canThrow()) {
3577e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    exceptionHandlers[i] = currentExceptionHandlers;
3587e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                }
359d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            }
360d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
361d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
362d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //finally, populate the successors and predecessors for each instruction
363fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert instructions.size() > 0;
364fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        addPredecessorSuccessor(startOfMethod, instructions.valueAt(0), exceptionHandlers);
365fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        startOfMethod.addSuccessor(instructions.valueAt(0));
366fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
367fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        for (int i=0; i<instructions.size(); i++) {
368fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            AnalyzedInstruction instruction = instructions.valueAt(i);
369d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            Opcode instructionOpcode = instruction.instruction.opcode;
370fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            int instructionCodeAddress = getInstructionAddress(instruction);
371d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
372d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            if (instruction.instruction.opcode.canContinue()) {
373c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                if (instruction.instruction.opcode != Opcode.NOP ||
374c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    !instruction.instruction.getFormat().variableSizeFormat) {
375c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
376c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    if (i == instructions.size() - 1) {
377c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        throw new ValidationException("Execution can continue past the last instruction");
378c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    }
379c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
380c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    AnalyzedInstruction nextInstruction = instructions.valueAt(i+1);
381c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    addPredecessorSuccessor(instruction, nextInstruction, exceptionHandlers);
382d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                }
383d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            }
384d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
3857e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            if (instruction.instruction instanceof OffsetInstruction) {
3867e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                OffsetInstruction offsetInstruction = (OffsetInstruction)instruction.instruction;
387d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
388d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                if (instructionOpcode == Opcode.PACKED_SWITCH || instructionOpcode == Opcode.SPARSE_SWITCH) {
389d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                    MultiOffsetInstruction switchDataInstruction =
390fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                            (MultiOffsetInstruction)instructions.get(instructionCodeAddress +
391d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                                    offsetInstruction.getTargetAddressOffset()).instruction;
392d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                    for (int targetAddressOffset: switchDataInstruction.getTargets()) {
393fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                        AnalyzedInstruction targetInstruction = instructions.get(instructionCodeAddress +
394d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                                targetAddressOffset);
395d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
396fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                        addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers);
397d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                    }
398d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                } else {
399d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                    int targetAddressOffset = offsetInstruction.getTargetAddressOffset();
400fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    AnalyzedInstruction targetInstruction = instructions.get(instructionCodeAddress +
401fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                            targetAddressOffset);
402fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers);
403d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com                }
404d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            }
405d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
406d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    }
407d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
408d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    private void addPredecessorSuccessor(AnalyzedInstruction predecessor, AnalyzedInstruction successor,
409fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                                                AnalyzedInstruction[][] exceptionHandlers) {
410fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        addPredecessorSuccessor(predecessor, successor, exceptionHandlers, false);
411fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
412fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
413fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private void addPredecessorSuccessor(AnalyzedInstruction predecessor, AnalyzedInstruction successor,
414fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                                                AnalyzedInstruction[][] exceptionHandlers, boolean allowMoveException) {
415fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
416fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (!allowMoveException && successor.instruction.opcode == Opcode.MOVE_EXCEPTION) {
417fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("Execution can pass from the " + predecessor.instruction.opcode.name +
418fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    " instruction at code address 0x" + Integer.toHexString(getInstructionAddress(predecessor)) +
419fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    " to the move-exception instruction at address 0x" +
420fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    Integer.toHexString(getInstructionAddress(successor)));
421fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
422d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
423d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        if (!predecessor.addSuccessor(successor)) {
424d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            //if predecessor already had successor as a successor, then there's nothing else to do
425d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            return;
426d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
427d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
428d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        successor.addPredecessor(predecessor);
429d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
430fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: need to handle the case of monitor-exit as a special case - the exception is thrown *after* the instruction executes
431d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //if the successor can throw an instruction, then we need to add the exception handlers as additional
432d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        //successors to the predecessor (and then apply this same logic recursively if needed)
433fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        AnalyzedInstruction[] exceptionHandlersForSuccessor = exceptionHandlers[successor.instructionIndex];
434d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        if (exceptionHandlersForSuccessor != null) {
435d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            //the item for this instruction in exceptionHandlersForSuccessor should only be set if this instruction
436d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            //can throw an exception
437c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            assert successor.instruction.opcode.canThrow();
438d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
439fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            for (AnalyzedInstruction exceptionHandler: exceptionHandlersForSuccessor) {
440fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                addPredecessorSuccessor(predecessor, exceptionHandler, exceptionHandlers, true);
441d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            }
442d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
443d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    }
444d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
445fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private AnalyzedInstruction[] buildExceptionHandlerArray(CodeItem.TryItem tryItem) {
446d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        int exceptionHandlerCount = tryItem.encodedCatchHandler.handlers.length;
447d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        int catchAllHandler = tryItem.encodedCatchHandler.getCatchAllHandlerAddress();
448d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        if (catchAllHandler != -1) {
449d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            exceptionHandlerCount++;
450d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
451d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
452fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        AnalyzedInstruction[] exceptionHandlers = new AnalyzedInstruction[exceptionHandlerCount];
453d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        for (int i=0; i<tryItem.encodedCatchHandler.handlers.length; i++) {
454fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            exceptionHandlers[i] = instructions.get(tryItem.encodedCatchHandler.handlers[i].getHandlerAddress());
455d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
456d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
457d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        if (catchAllHandler != -1) {
458fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            exceptionHandlers[exceptionHandlers.length - 1] = instructions.get(catchAllHandler);
459d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
460d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
461d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        return exceptionHandlers;
462d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    }
463d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
464ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void analyzeInstruction(AnalyzedInstruction analyzedInstruction) {
465fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        Instruction instruction = analyzedInstruction.instruction;
466fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
467fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        switch (instruction.opcode) {
468fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case NOP:
469ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
470fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE:
471fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_FROM16:
472fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_16:
473ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleMove(analyzedInstruction, Primitive32BitCategories);
474ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
475fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_WIDE:
476fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_WIDE_FROM16:
477fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_WIDE_16:
47885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                handleMove(analyzedInstruction, WideLowCategories);
479ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
480fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_OBJECT:
481fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_OBJECT_FROM16:
482fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_OBJECT_16:
4837e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                handleMove(analyzedInstruction, ReferenceOrUninitCategories);
484ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
485fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_RESULT:
486ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleMoveResult(analyzedInstruction, Primitive32BitCategories);
487ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
488fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_RESULT_WIDE:
489ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleMoveResult(analyzedInstruction, WideLowCategories);
490ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
491fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_RESULT_OBJECT:
492ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleMoveResult(analyzedInstruction, ReferenceCategories);
493ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
494fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MOVE_EXCEPTION:
495ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleMoveException(analyzedInstruction);
496ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
497fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case RETURN_VOID:
498ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleReturnVoid(analyzedInstruction);
499ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
500fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case RETURN:
50185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                handleReturn(analyzedInstruction, Primitive32BitCategories);
502ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
503fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case RETURN_WIDE:
50485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                handleReturn(analyzedInstruction, WideLowCategories);
505ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
506fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case RETURN_OBJECT:
50785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                handleReturn(analyzedInstruction, ReferenceCategories);
508ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
509fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_4:
510fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_16:
511fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST:
512ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleConst(analyzedInstruction);
513ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
514fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_HIGH16:
515ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleConstHigh16(analyzedInstruction);
516ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
517fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_WIDE_16:
518fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_WIDE_32:
519fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_WIDE:
520fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_WIDE_HIGH16:
521ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleWideConst(analyzedInstruction);
522ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
523fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_STRING:
524fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_STRING_JUMBO:
525ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleConstString(analyzedInstruction);
526ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
527fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CONST_CLASS:
528ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleConstClass(analyzedInstruction);
529ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
530fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MONITOR_ENTER:
531fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case MONITOR_EXIT:
532ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleMonitor(analyzedInstruction);
533ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
534fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case CHECK_CAST:
535ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleCheckCast(analyzedInstruction);
536ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
537fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case INSTANCE_OF:
538ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInstanceOf(analyzedInstruction);
539ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
540fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case ARRAY_LENGTH:
541ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleArrayLength(analyzedInstruction);
542ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
543fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case NEW_INSTANCE:
544ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleNewInstance(analyzedInstruction);
545ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
546fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            case NEW_ARRAY:
547ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleNewArray(analyzedInstruction);
548ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
5499e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com            case FILLED_NEW_ARRAY:
550ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleFilledNewArray(analyzedInstruction);
551ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
552ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com            case FILLED_NEW_ARRAY_RANGE:
553ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleFilledNewArrayRange(analyzedInstruction);
554ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
555472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case FILL_ARRAY_DATA:
556ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleFillArrayData(analyzedInstruction);
557ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
558ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com            case THROW:
559ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleThrow(analyzedInstruction);
560ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
561898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com            case GOTO:
562898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com            case GOTO_16:
563898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com            case GOTO_32:
564898edda7cea48c02687bb71804a98cfd6e260b89JesusFreke@JesusFreke.com                //nothing to do
565ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
566cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com            case PACKED_SWITCH:
567ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleSwitch(analyzedInstruction, Format.PackedSwitchData);
568ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
569cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com            case SPARSE_SWITCH:
570ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleSwitch(analyzedInstruction, Format.SparseSwitchData);
571ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
572f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com            case CMPL_FLOAT:
573f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com            case CMPG_FLOAT:
57485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                handleFloatWideCmp(analyzedInstruction, Primitive32BitCategories);
575ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
576f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com            case CMPL_DOUBLE:
577f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com            case CMPG_DOUBLE:
578f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com            case CMP_LONG:
57985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                handleFloatWideCmp(analyzedInstruction, WideLowCategories);
580ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
581aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com            case IF_EQ:
582aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com            case IF_NE:
583ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIfEqNe(analyzedInstruction);
584ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
585150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com            case IF_LT:
586150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com            case IF_GE:
587150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com            case IF_GT:
588150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com            case IF_LE:
589ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIf(analyzedInstruction);
590ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
591cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com            case IF_EQZ:
592cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com            case IF_NEZ:
593ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIfEqzNez(analyzedInstruction);
594ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
59516a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com            case IF_LTZ:
59616a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com            case IF_GEZ:
59716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com            case IF_GTZ:
59816a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com            case IF_LEZ:
599ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIfz(analyzedInstruction);
600ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
601b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            case AGET:
602ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Integer);
603ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
604b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            case AGET_BOOLEAN:
605ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Boolean);
606ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
607b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            case AGET_BYTE:
608ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Byte);
609ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
610b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            case AGET_CHAR:
611ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Char);
612ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
613b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            case AGET_SHORT:
614ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAget(analyzedInstruction, RegisterType.Category.Short);
615ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
616c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            case AGET_WIDE:
617ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleAgetWide(analyzedInstruction);
618ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
619461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            case AGET_OBJECT:
620ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleAgetObject(analyzedInstruction);
621ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
622c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            case APUT:
623ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Integer);
624ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
625c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            case APUT_BOOLEAN:
626ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Boolean);
627ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
628c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            case APUT_BYTE:
629ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Byte);
630ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
631c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            case APUT_CHAR:
632ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Char);
633ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
634c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            case APUT_SHORT:
635ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveAput(analyzedInstruction, RegisterType.Category.Short);
636ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
63755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            case APUT_WIDE:
638ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleAputWide(analyzedInstruction);
639ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
640898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            case APUT_OBJECT:
641ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleAputObject(analyzedInstruction);
642ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6434f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            case IGET:
644ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Integer);
645ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6464f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            case IGET_BOOLEAN:
647ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Boolean);
648ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6494f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            case IGET_BYTE:
650ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Byte);
651ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6524f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            case IGET_CHAR:
653ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Char);
654ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6554f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            case IGET_SHORT:
656ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Short);
657ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6589d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com            case IGET_WIDE:
659ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIgetWide(analyzedInstruction);
660ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6617a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com            case IGET_OBJECT:
662ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIgetObject(analyzedInstruction);
663ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6649971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            case IPUT:
665ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Integer);
666ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6679971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            case IPUT_BOOLEAN:
668ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Boolean);
669ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6709971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            case IPUT_BYTE:
671ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Byte);
672ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6739971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            case IPUT_CHAR:
674ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Char);
675ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
6769971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            case IPUT_SHORT:
677ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveIput(analyzedInstruction, RegisterType.Category.Short);
678ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
67992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com            case IPUT_WIDE:
680ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIputWide(analyzedInstruction);
681ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
68250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            case IPUT_OBJECT:
683ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleIputObject(analyzedInstruction);
684ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
685052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com            case SGET:
686ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Integer);
687ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
688052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com            case SGET_BOOLEAN:
689ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Boolean);
690ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
691052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com            case SGET_BYTE:
692ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Byte);
693ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
694052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com            case SGET_CHAR:
695ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Char);
696ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
697052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com            case SGET_SHORT:
698ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Short);
699ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7002f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com            case SGET_WIDE:
701ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleSgetWide(analyzedInstruction);
702ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7032d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com            case SGET_OBJECT:
704ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleSgetObject(analyzedInstruction);
705ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7069d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            case SPUT:
707ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Integer);
708ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7099d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            case SPUT_BOOLEAN:
710ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Boolean);
711ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7129d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            case SPUT_BYTE:
713ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Byte);
714ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7159d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            case SPUT_CHAR:
716ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Char);
717ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7189d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            case SPUT_SHORT:
719ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handle32BitPrimitiveSput(analyzedInstruction, RegisterType.Category.Short);
720ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
721f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com            case SPUT_WIDE:
722ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleSputWide(analyzedInstruction);
723ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
72451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com            case SPUT_OBJECT:
725ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleSputObject(analyzedInstruction);
726ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
72789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_VIRTUAL:
728ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvoke(analyzedInstruction, INVOKE_VIRTUAL);
729ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
73089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_SUPER:
731ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvoke(analyzedInstruction, INVOKE_SUPER);
732ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
73389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_DIRECT:
734ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvoke(analyzedInstruction, INVOKE_DIRECT);
735ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
73689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_STATIC:
737ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvoke(analyzedInstruction, INVOKE_STATIC);
738ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
73989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_INTERFACE:
740ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvoke(analyzedInstruction, INVOKE_INTERFACE);
741ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
74289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_VIRTUAL_RANGE:
743ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvokeRange(analyzedInstruction, INVOKE_VIRTUAL);
744ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
74589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_SUPER_RANGE:
746ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvokeRange(analyzedInstruction, INVOKE_SUPER);
747ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
74889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_DIRECT_RANGE:
749ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvokeRange(analyzedInstruction, INVOKE_DIRECT);
750ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
75189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_STATIC_RANGE:
752ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvokeRange(analyzedInstruction, INVOKE_STATIC);
753ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
75489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            case INVOKE_INTERFACE_RANGE:
755ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                handleInvokeRange(analyzedInstruction, INVOKE_INTERFACE);
756ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com                return;
7571483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case NEG_INT:
7581483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case NOT_INT:
7591483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer);
7601483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7611483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case NEG_LONG:
7621483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case NOT_LONG:
7631483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.LongLo);
7641483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7651483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case NEG_FLOAT:
7661483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Float);
7671483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7681483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case NEG_DOUBLE:
7691483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.DoubleLo);
7701483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7711483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case INT_TO_LONG:
7721483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.LongLo);
7731483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7741483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case INT_TO_FLOAT:
7751483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Float);
7761483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7771483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case INT_TO_DOUBLE:
7781483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.DoubleLo);
7791483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7801483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case LONG_TO_INT:
7811483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case DOUBLE_TO_INT:
7821483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.Integer);
7831483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7841483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case LONG_TO_FLOAT:
7851483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case DOUBLE_TO_FLOAT:
7861483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.Float);
7871483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7881483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case LONG_TO_DOUBLE:
7891483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.DoubleLo);
7901483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7911483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case FLOAT_TO_INT:
7921483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer);
7931483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7941483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case FLOAT_TO_LONG:
7951483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.LongLo);
7961483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
7971483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case FLOAT_TO_DOUBLE:
7981483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.DoubleLo);
7991483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
8001483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case DOUBLE_TO_LONG:
8011483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, WideLowCategories, RegisterType.Category.LongLo);
8021483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
8031483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case INT_TO_BYTE:
8041483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Byte);
8051483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
8061483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case INT_TO_CHAR:
8071483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Char);
8081483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
8091483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com            case INT_TO_SHORT:
8101483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                handleUnaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Short);
8111483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                return;
812195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case ADD_INT:
813195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SUB_INT:
814195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case MUL_INT:
815195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case DIV_INT:
816195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case REM_INT:
817195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SHL_INT:
818195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SHR_INT:
819195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case USHR_INT:
820195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                handleBinaryOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories,
821195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                        RegisterType.Category.Integer, false);
822195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                return;
823195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case AND_INT:
824195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case OR_INT:
825195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case XOR_INT:
826195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                handleBinaryOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories,
827195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                        RegisterType.Category.Integer, true);
828c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                return;
829195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case ADD_LONG:
830195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SUB_LONG:
831195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case MUL_LONG:
832195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case DIV_LONG:
833195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case REM_LONG:
834195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case AND_LONG:
835195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case OR_LONG:
836195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case XOR_LONG:
837195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                handleBinaryOp(analyzedInstruction, WideLowCategories, WideLowCategories, RegisterType.Category.LongLo,
838195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                        false);
839195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                return;
840195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SHL_LONG:
841195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SHR_LONG:
842195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case USHR_LONG:
843195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                handleBinaryOp(analyzedInstruction, WideLowCategories, Primitive32BitCategories,
844195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                        RegisterType.Category.LongLo, false);
845195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                return;
846195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case ADD_FLOAT:
847195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SUB_FLOAT:
848195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case MUL_FLOAT:
849195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case DIV_FLOAT:
850195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case REM_FLOAT:
851195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                handleBinaryOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories,
852195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                        RegisterType.Category.Float, false);
853195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                return;
854195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case ADD_DOUBLE:
855195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case SUB_DOUBLE:
856195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case MUL_DOUBLE:
857195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case DIV_DOUBLE:
858195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            case REM_DOUBLE:
859195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                handleBinaryOp(analyzedInstruction, WideLowCategories, WideLowCategories,
860195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                        RegisterType.Category.DoubleLo, false);
861195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                return;
862122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case ADD_INT_2ADDR:
863122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SUB_INT_2ADDR:
864122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case MUL_INT_2ADDR:
865122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case DIV_INT_2ADDR:
866122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case REM_INT_2ADDR:
867122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SHL_INT_2ADDR:
868122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SHR_INT_2ADDR:
869122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case USHR_INT_2ADDR:
870122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                handleBinary2AddrOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories,
871122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                        RegisterType.Category.Integer, false);
872122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                return;
873122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case AND_INT_2ADDR:
874122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case OR_INT_2ADDR:
875122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case XOR_INT_2ADDR:
876122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                handleBinary2AddrOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories,
877122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                        RegisterType.Category.Integer, true);
878122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                return;
879122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case ADD_LONG_2ADDR:
880122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SUB_LONG_2ADDR:
881122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case MUL_LONG_2ADDR:
882122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case DIV_LONG_2ADDR:
883122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case REM_LONG_2ADDR:
884122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case AND_LONG_2ADDR:
885122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case OR_LONG_2ADDR:
886122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case XOR_LONG_2ADDR:
887122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                handleBinary2AddrOp(analyzedInstruction, WideLowCategories, WideLowCategories,
888122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                        RegisterType.Category.LongLo, false);
889122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                return;
890122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SHL_LONG_2ADDR:
891122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SHR_LONG_2ADDR:
892122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case USHR_LONG_2ADDR:
893122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                handleBinary2AddrOp(analyzedInstruction, WideLowCategories, Primitive32BitCategories,
894122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                        RegisterType.Category.LongLo, false);
895122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                return;
896122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case ADD_FLOAT_2ADDR:
897122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SUB_FLOAT_2ADDR:
898122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case MUL_FLOAT_2ADDR:
899122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case DIV_FLOAT_2ADDR:
900122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case REM_FLOAT_2ADDR:
901122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                handleBinary2AddrOp(analyzedInstruction, Primitive32BitCategories, Primitive32BitCategories,
902122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                        RegisterType.Category.Float, false);
903122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                return;
904122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case ADD_DOUBLE_2ADDR:
905122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case SUB_DOUBLE_2ADDR:
906122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case MUL_DOUBLE_2ADDR:
907122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case DIV_DOUBLE_2ADDR:
908122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            case REM_DOUBLE_2ADDR:
909122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                handleBinary2AddrOp(analyzedInstruction, WideLowCategories, WideLowCategories,
910122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                        RegisterType.Category.DoubleLo, false);
911122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                return;
912caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case ADD_INT_LIT16:
913caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case RSUB_INT:
914caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case MUL_INT_LIT16:
915caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case DIV_INT_LIT16:
916caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case REM_INT_LIT16:
917caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
918caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        false);
919caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return;
920caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case AND_INT_LIT16:
921caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case OR_INT_LIT16:
922caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case XOR_INT_LIT16:
923caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
924caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        true);
925caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return;
926caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case ADD_INT_LIT8:
927caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case RSUB_INT_LIT8:
928caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case MUL_INT_LIT8:
929caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case DIV_INT_LIT8:
930caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case REM_INT_LIT8:
931caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case SHL_INT_LIT8:
932caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
933caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        false);
934caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return;
935caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case AND_INT_LIT8:
936caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case OR_INT_LIT8:
937caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case XOR_INT_LIT8:
938caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories, RegisterType.Category.Integer,
939caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        true);
940caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return;
941caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case SHR_INT_LIT8:
942caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories,
943caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        getDestTypeForLiteralShiftRight(analyzedInstruction, true), false);
944caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return;
945caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case USHR_INT_LIT8:
946caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                handleLiteralBinaryOp(analyzedInstruction, Primitive32BitCategories,
947caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        getDestTypeForLiteralShiftRight(analyzedInstruction, false), false);
948caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return;
949caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            default:
950caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                assert false;
951fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
952fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
953fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
954fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> Primitive32BitCategories = EnumSet.of(
955fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Null,
9567e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.One,
957fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Boolean,
958fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Byte,
9597e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.PosByte,
960fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Short,
9617e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.PosShort,
962fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Char,
963fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Integer,
964fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Float);
965fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
966fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> WideLowCategories = EnumSet.of(
967fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.LongLo,
968fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.DoubleLo);
969fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
970fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> WideHighCategories = EnumSet.of(
971fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.LongHi,
972fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.DoubleHi);
973fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
974fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> ReferenceCategories = EnumSet.of(
975fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Null,
976fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType.Category.Reference);
977fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
978c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> ReferenceOrUninitThisCategories = EnumSet.of(
979c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            RegisterType.Category.Null,
980c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            RegisterType.Category.UninitThis,
981c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            RegisterType.Category.Reference);
982c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
9837e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> ReferenceOrUninitCategories = EnumSet.of(
9847e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.Null,
9857e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.UninitRef,
986c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            RegisterType.Category.UninitThis,
9877e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.Reference);
9887e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
98985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> ReferenceAndPrimitive32BitCategories = EnumSet.of(
99085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Null,
9917e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.One,
99285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Boolean,
99385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Byte,
9947e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.PosByte,
99585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Short,
9967e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            RegisterType.Category.PosShort,
99785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Char,
99885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Integer,
99985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Float,
100085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType.Category.Reference);
1001fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1002195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com    private static final EnumSet<RegisterType.Category> BooleanCategories = EnumSet.of(
1003195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            RegisterType.Category.Null,
1004195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            RegisterType.Category.One,
1005195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            RegisterType.Category.Boolean);
1006fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
100785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private void handleMove(AnalyzedInstruction analyzedInstruction, EnumSet validCategories) {
1008fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
1009fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
101085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
101185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                validCategories);
1012fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1013fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, sourceRegisterType);
1014fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1015fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1016ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleMoveResult(AnalyzedInstruction analyzedInstruction,
1017fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                                     EnumSet<RegisterType.Category> allowedCategories) {
1018fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1019fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: handle the case when the previous instruction is an odexed instruction
1020fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1021fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (analyzedInstruction.instructionIndex == 0) {
1022fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException(analyzedInstruction.instruction.opcode.name + " cannot be the first " +
1023fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    "instruction in a method. It must occur after an invoke-*/fill-new-array instruction");
1024fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1025fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1026fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1);
1027fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1028fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (!previousInstruction.instruction.opcode.setsResult()) {
1029fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " +
1030fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    "invoke-*/fill-new-array instruction");
1031fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1032fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1033fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: does dalvik allow a move-result after an invoke with a void return type?
103485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType resultRegisterType;
1035fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1036fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.instruction;
1037fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        Item item = invokeInstruction.getReferencedItem();
1038fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1039fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (item instanceof MethodIdItem) {
104085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem(
1041fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    ((MethodIdItem)item).getPrototype().getReturnType());
1042fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        } else {
1043fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            assert item instanceof TypeIdItem;
104485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item);
104585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
104685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com
104785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (!allowedCategories.contains(resultRegisterType.category)) {
104885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Wrong move-result* instruction for return value %s",
104985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    resultRegisterType.toString()));
1050fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1051fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
105285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, resultRegisterType);
1053fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1054fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1055ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleMoveException(AnalyzedInstruction analyzedInstruction) {
1056fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        CodeItem.TryItem[] tries = encodedMethod.codeItem.getTries();
1057fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int instructionAddress = getInstructionAddress(analyzedInstruction);
1058fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1059fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (tries == null) {
1060fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("move-exception must be the first instruction in an exception handler block");
1061fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1062fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1063fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType exceptionType = null;
1064fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1065fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) {
1066fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            if (tryItem.encodedCatchHandler.getCatchAllHandlerAddress() == instructionAddress) {
1067fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                exceptionType = RegisterType.getRegisterType(RegisterType.Category.Reference,
1068fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                        ClassPath.getClassDef("Ljava/lang/Throwable;"));
1069fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                break;
1070fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
1071fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
1072fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                if (handler.getHandlerAddress() == instructionAddress) {
1073fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    exceptionType = RegisterType.getRegisterTypeForTypeIdItem(handler.exceptionType)
1074fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                            .merge(exceptionType);
1075fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                }
1076fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
1077fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1078fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
107985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (exceptionType == null) {
108085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException("move-exception must be the first instruction in an exception handler block");
108185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
108285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com
1083fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: check if the type is a throwable. Should we throw a ValidationException or print a warning? (does dalvik validate that it's a throwable? It doesn't in CodeVerify.c, but it might check in DexSwapVerify.c)
108485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (exceptionType.category != RegisterType.Category.Reference) {
108585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Exception type %s is not a reference type",
108685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    exceptionType.toString()));
108785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
108885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com
1089fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, exceptionType);
1090fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1091fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1092c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    //TODO: GROT
1093c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    /*private void checkConstructorReturn(AnalyzedInstruction analyzedInstruction) {
1094fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert this.isInstanceConstructor();
1095fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1096fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //if we're in an instance constructor (an <init> method), then the superclass <init> must have been called.
1097fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //When execution enters the method, the "this" register is set as an uninitialized reference to the containing
1098fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //class. Once the superclass' <init> is called, the "this" register is upgraded to a full-blown reference type,
1099fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //so we need to ensure that the "this" register isn't an uninitialized reference
1100fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1101fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int thisRegister = getThisRegister();
1102fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType thisRegisterType = analyzedInstruction.postRegisterMap[thisRegister];
1103fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1104fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (thisRegisterType.category == RegisterType.Category.UninitRef) {
1105fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("Returning from constructor without calling the superclass' <init>");
1106fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
11077e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        //TODO: GROT
11087e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        //assert thisRegisterType.category == RegisterType.Category.Reference;
11097e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        //assert thisRegisterType.type == ClassPath.getClassDef(encodedMethod.method.getContainingClass());
1110c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    }*/
1111fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1112ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleReturnVoid(AnalyzedInstruction analyzedInstruction) {
1113c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        /*if (this.isInstanceConstructor()) {
1114ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com            checkConstructorReturn(analyzedInstruction);
1115c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        }*/
1116fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1117fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType();
1118fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (returnType.getTypeDescriptor().charAt(0) != 'V') {
1119fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //TODO: could add which return-* variation should be used instead
1120fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("Cannot use return-void with a non-void return type (" +
1121fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                returnType.getTypeDescriptor() + ")");
1122fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1123fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1124fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
112585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private void handleReturn(AnalyzedInstruction analyzedInstruction, EnumSet validCategories) {
1126c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        /*if (this.isInstanceConstructor()) {
1127ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com            checkConstructorReturn(analyzedInstruction);
1128c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        }*/
1129fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1130fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
113185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        int returnRegister = instruction.getRegisterA();
113285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType returnRegisterType = getAndCheckSourceRegister(analyzedInstruction, returnRegister,
113385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                validCategories);
1134fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1135fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType();
1136fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (returnType.getTypeDescriptor().charAt(0) == 'V') {
1137fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("Cannot use return with a void return type. Use return-void instead");
1138fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1139fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
114085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType methodReturnRegisterType = RegisterType.getRegisterTypeForTypeIdItem(returnType);
1141fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
114285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (!validCategories.contains(methodReturnRegisterType.category)) {
1143fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //TODO: could add which return-* variation should be used instead
114485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with return type %s",
114585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    analyzedInstruction.instruction.opcode.name, returnType.getTypeDescriptor()));
1146fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1147fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
114885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (validCategories == ReferenceCategories) {
114985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            if (methodReturnRegisterType.type.isInterface()) {
1150c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                if (returnRegisterType.category != RegisterType.Category.Null &&
1151c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    !returnRegisterType.type.implementsInterface(methodReturnRegisterType.type)) {
115285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    //TODO: how to handle warnings?
115385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                }
115485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            } else {
1155c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                if (returnRegisterType.category == RegisterType.Category.Reference &&
1156c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    !returnRegisterType.type.extendsClass(methodReturnRegisterType.type)) {
1157c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
115885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    throw new ValidationException(String.format("The return value in register v%d (%s) is not " +
115985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                            "compatible with the method's return type %s", returnRegister,
116085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                            returnRegisterType.type.getClassType(), methodReturnRegisterType.type.getClassType()));
116185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                }
1162fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
1163fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1164fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1165fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1166ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleConst(AnalyzedInstruction analyzedInstruction) {
1167fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction;
1168fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1169fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(instruction.getLiteral());
1170fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1171fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //we assume that the literal value is a valid value for the given instruction type, because it's impossible
1172fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //to store an invalid literal with the instruction. so we don't need to check the type of the literal
1173fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType);
1174fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1175fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1176ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleConstHigh16(AnalyzedInstruction analyzedInstruction) {
1177fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        LiteralInstruction instruction = (LiteralInstruction)analyzedInstruction.instruction;
1178fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1179fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: test this
1180fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        long literalValue = instruction.getLiteral() << 16;
1181fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType newDestinationRegisterType = RegisterType.getRegisterTypeForLiteral(literalValue);
1182fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1183fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //we assume that the literal value is a valid value for the given instruction type, because it's impossible
1184fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //to store an invalid literal with the instruction. so we don't need to check the type of the literal
1185fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, newDestinationRegisterType);
1186fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1187fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1188ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleWideConst(AnalyzedInstruction analyzedInstruction) {
118985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1190fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                RegisterType.getRegisterType(RegisterType.Category.LongLo, null));
1191fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1192fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1193ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleConstString(AnalyzedInstruction analyzedInstruction) {
1194fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        ClassPath.ClassDef stringClassDef = ClassPath.getClassDef("Ljava/lang/String;");
1195fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType stringType = RegisterType.getRegisterType(RegisterType.Category.Reference, stringClassDef);
1196fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, stringType);
1197fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1198fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1199ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleConstClass(AnalyzedInstruction analyzedInstruction) {
1200fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        ClassPath.ClassDef classClassDef = ClassPath.getClassDef("Ljava/lang/Class;");
1201fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType classType = RegisterType.getRegisterType(RegisterType.Category.Reference, classClassDef);
1202fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1203fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
1204fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        Item item = instruction.getReferencedItem();
1205fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
1206fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1207fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: need to check class access
1208c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        //make sure the referenced class is resolvable
1209c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        ClassPath.getClassDef((TypeIdItem)item);
1210c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
1211c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, classType);
1212fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1213fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1214ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleMonitor(AnalyzedInstruction analyzedInstruction) {
121585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
121685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), ReferenceCategories);
1217fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1218fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1219ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleCheckCast(AnalyzedInstruction analyzedInstruction) {
1220fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        {
1221fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //ensure the "source" register is a reference type
1222fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
1223fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
122485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType registerType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(),
122585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    ReferenceCategories);
1226fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1227fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1228fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        {
1229fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //resolve and verify the class that we're casting to
1230fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
1231fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1232fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            Item item = instruction.getReferencedItem();
1233fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
1234fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1235fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //TODO: need to check class access
123685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType castRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item);
123785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            if (castRegisterType.category != RegisterType.Category.Reference) {
1238fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                //TODO: verify that dalvik allows a non-reference type..
1239fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                //TODO: print a warning, but don't re-throw the exception. dalvik allows a non-reference type during validation (but throws an exception at runtime)
1240fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            }
1241fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
124285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, castRegisterType);
1243fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1244fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1245fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1246ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleInstanceOf(AnalyzedInstruction analyzedInstruction) {
1247fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        {
1248fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //ensure the register that is being checks is a reference type
124985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
1250fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
125185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), ReferenceCategories);
1252fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1253fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1254fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        {
1255fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //resolve and verify the class that we're checking against
1256fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
1257fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1258fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            Item item = instruction.getReferencedItem();
1259fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            assert  item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
1260fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            RegisterType registerType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item);
126185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            if (registerType.category != RegisterType.Category.Reference) {
126285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use instance-of with a non-reference type %s",
126385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                        registerType.toString()));
126485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            }
1265fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1266fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //TODO: is it valid to use an array type?
1267fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1268fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            //TODO: could probably do an even more sophisticated check, where we check the possible register types against the specified type. In some cases, we could determine that it always fails, and print a warning to that effect.
1269fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1270fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    RegisterType.getRegisterType(RegisterType.Category.Boolean, null));
1271fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1272fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1273fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1274ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleArrayLength(AnalyzedInstruction analyzedInstruction) {
127585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
1276fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1277fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        int arrayRegisterNumber = instruction.getRegisterB();
127885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType arrayRegisterType = getAndCheckSourceRegister(analyzedInstruction, arrayRegisterNumber,
127985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                ReferenceCategories);
1280fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1281fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (arrayRegisterType.type != null) {
1282fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
128385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use array-length with non-array type %s",
128485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
1285d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com            }
1286c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
1287d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
1288d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
1289fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1290fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                RegisterType.getRegisterType(RegisterType.Category.Integer, null));
1291fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1292fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1293ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleNewInstance(AnalyzedInstruction analyzedInstruction) {
1294fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
1295fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1296a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com        int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA();
1297a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com        RegisterType destRegisterType = analyzedInstruction.postRegisterMap[register];
1298a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com        if (destRegisterType.category != RegisterType.Category.Unknown) {
1299a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            assert destRegisterType.category == RegisterType.Category.UninitRef;
1300a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com
1301a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            //the "post-instruction" destination register will only be set if we've gone over
1302a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            //this instruction at least once before. If this is the case, then we need to check
1303a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            //all the other registers, and make sure that none of them contain the same
1304a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            //uninitialized reference that is in the destination register.
1305a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com
1306a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            for (int i=0; i<analyzedInstruction.postRegisterMap.length; i++) {
1307a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                if (i==register) {
1308a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                    continue;
1309a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                }
1310a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com
1311a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                if (analyzedInstruction.getPreInstructionRegisterType(i) == destRegisterType) {
1312a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                    throw new ValidationException(String.format("Register v%d contains an uninitialized reference " +
1313a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                            "that was created by this new-instance instruction.", i));
1314a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                }
1315a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com            }
1316c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
1317c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            return;
1318a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com        }
1319a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com
1320fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        Item item = instruction.getReferencedItem();
1321fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
1322fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1323fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        //TODO: need to check class access
1324fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType classType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item);
132585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (classType.category != RegisterType.Category.Reference) {
132685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use new-instance with a non-reference type %s",
132785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    classType.toString()));
132885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
132985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com
1330fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (((TypeIdItem)item).getTypeDescriptor().charAt(0) == '[') {
1331fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("Cannot use array type \"" + ((TypeIdItem)item).getTypeDescriptor() +
1332fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    "\" with new-instance. Use new-array instead.");
1333d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com        }
1334d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
1335fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1336a0314c265e76426e3e05e615cc713cf36c78cb85JesusFreke@JesusFreke.com                RegisterType.getUnitializedReference(classType.type));
1337fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1338fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1339ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleNewArray(AnalyzedInstruction analyzedInstruction) {
1340fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        {
1341fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
134285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), Primitive32BitCategories);
1343fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1344fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1345fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
1346fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1347fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        Item item = instruction.getReferencedItem();
1348fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
1349fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1350fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        RegisterType arrayType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item);
1351fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        assert arrayType.type instanceof ClassPath.ArrayClassDef;
1352d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
135385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (arrayType.category != RegisterType.Category.Reference) {
135485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use new-array with a non-reference type %s",
135585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    arrayType.toString()));
135685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
1357fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        if (arrayType.type.getClassType().charAt(0) != '[') {
1358fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com            throw new ValidationException("Cannot use non-array type \"" + arrayType.type.getClassType() +
1359fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com                    "\" with new-array. Use new-instance instead.");
1360fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
1361fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1362fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType);
1363fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com    }
1364fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
1365ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com    private static interface RegisterIterator {
1366ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        int getRegister();
1367ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        boolean moveNext();
136806d1aacf61792afcdb273cf458e1e3daead0cf85JesusFreke@JesusFreke.com        int getCount();
13696192896f88638177ab6a5e64535f834f4a08b726JesusFreke@JesusFreke.com        boolean pastEnd();
1370ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com    }
1371ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com
1372b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com    private static class Format35cRegisterIterator implements RegisterIterator {
1373b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        private final int registerCount;
1374b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        private final int[] registers;
1375b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        private int currentRegister = 0;
1376b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1377b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public Format35cRegisterIterator(FiveRegisterInstruction instruction) {
1378b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            registerCount = instruction.getRegCount();
1379b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            registers = new int[]{instruction.getRegisterD(), instruction.getRegisterE(),
1380b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com                                  instruction.getRegisterF(), instruction.getRegisterG(),
1381b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com                                  instruction.getRegisterA()};
1382b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1383b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1384b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public int getRegister() {
1385b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            return registers[currentRegister];
1386b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1387b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1388b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public boolean moveNext() {
1389b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            currentRegister++;
1390c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            return !pastEnd();
1391b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1392b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1393b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public int getCount() {
1394b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            return registerCount;
1395b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1396b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1397b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public boolean pastEnd() {
1398b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            return currentRegister >= registerCount;
1399b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1400b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com    }
1401b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1402b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com    private static class Format3rcRegisterIterator implements RegisterIterator {
1403b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        private final int startRegister;
1404b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        private final int registerCount;
1405b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        private int currentRegister = 0;
1406b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1407b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public Format3rcRegisterIterator(RegisterRangeInstruction instruction) {
1408b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            startRegister = instruction.getStartRegister();
1409b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            registerCount = instruction.getRegCount();
1410b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1411b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1412b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public int getRegister() {
1413b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            return startRegister + currentRegister;
1414b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1415b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1416b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public boolean moveNext() {
1417b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            currentRegister++;
1418c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            return !pastEnd();
1419b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1420b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1421b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public int getCount() {
1422b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            return registerCount;
1423b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1424b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1425b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        public boolean pastEnd() {
1426b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com            return currentRegister >= registerCount;
1427b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        }
1428b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com    }
1429b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com
1430ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleFilledNewArrayCommon(AnalyzedInstruction analyzedInstruction,
1431ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com                                               RegisterIterator registerIterator) {
1432ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
1433ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com
14349e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com        RegisterType arrayType;
14359e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com        RegisterType arrayImmediateElementType;
14369e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
1437ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        Item item = instruction.getReferencedItem();
1438ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        assert  item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM;
14399e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
1440ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        ClassPath.ClassDef classDef = ClassPath.getClassDef((TypeIdItem)item);
14419e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
1442ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        if (classDef.getClassType().charAt(0) != '[') {
1443ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com            throw new ValidationException("Cannot use non-array type \"" + classDef.getClassType() +
1444ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com                "\" with new-array. Use new-instance instead.");
14459e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com        }
14469e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
1447ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)classDef;
1448ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        arrayType = RegisterType.getRegisterType(RegisterType.Category.Reference, classDef);
1449ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        arrayImmediateElementType = RegisterType.getRegisterTypeForType(
1450ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com                arrayClassDef.getImmediateElementClass().getClassType());
1451ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        String baseElementType = arrayClassDef.getBaseElementClass().getClassType();
1452ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        if (baseElementType.charAt(0) == 'J' || baseElementType.charAt(0) == 'D') {
1453ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com            throw new ValidationException("Cannot use filled-new-array to create an array of wide values " +
1454ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com                    "(long or double)");
1455ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        }
14569e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
1457ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        do {
1458ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com            int register = registerIterator.getRegister();
14599e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com            RegisterType elementType = analyzedInstruction.getPreInstructionRegisterType(register);
14609e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com            assert elementType != null;
14619e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
14629e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com            if (!elementType.canBeAssignedTo(arrayImmediateElementType)) {
14639e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com                throw new ValidationException("Register v" + Integer.toString(register) + " is of type " +
14649e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com                        elementType.toString() + " and is incompatible with the array type " +
14659e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com                        arrayType.type.getClassType());
14669e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com            }
1467ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        } while (registerIterator.moveNext());
14689e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com    }
14699e5dd85d837501e84e18617fc136c8203ab1f183JesusFreke@JesusFreke.com
1470ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleFilledNewArray(AnalyzedInstruction analyzedInstruction) {
1471ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction;
1472ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com        handleFilledNewArrayCommon(analyzedInstruction, new Format35cRegisterIterator(instruction));
1473ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com    }
1474ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com
1475ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleFilledNewArrayRange(AnalyzedInstruction analyzedInstruction) {
1476b615ba6f51a42428937236a640480d6f7f9dc511JesusFreke@JesusFreke.com        RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction;
1477ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com
1478ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        //instruction.getStartRegister() and instruction.getRegCount() both return an int value, but are actually
1479ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        //unsigned 16 bit values, so we don't have to worry about overflowing an int when adding them together
1480ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        if (instruction.getStartRegister() + instruction.getRegCount() >= 1<<16) {
1481ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Invalid register range {v%d .. v%d}. The ending register " +
1482472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                    "is larger than the largest allowed register of v65535.",
1483ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com                    instruction.getStartRegister(),
1484ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com                    instruction.getStartRegister() + instruction.getRegCount() - 1));
1485ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com        }
1486ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com
1487ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com        handleFilledNewArrayCommon(analyzedInstruction, new Format3rcRegisterIterator(instruction));
1488ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com    }
1489ac8785e5d550c2ec7c7d02dd2990f859a78c111cJesusFreke@JesusFreke.com
1490ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleFillArrayData(AnalyzedInstruction analyzedInstruction) {
1491472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
1492472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1493472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        int register = instruction.getRegisterA();
1494472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register);
1495472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        assert registerType != null;
1496472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1497ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com        if (registerType.category == RegisterType.Category.Null) {
1498ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com            return;
1499472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        }
1500472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1501472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        if (registerType.category != RegisterType.Category.Reference) {
1502472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use fill-array-data with non-array register v%d of " +
1503472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                    "type %s", register, registerType.toString()));
1504472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        }
1505472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1506472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        assert registerType.type instanceof ClassPath.ArrayClassDef;
1507472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)registerType.type;
1508472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1509472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        if (arrayClassDef.getArrayDimensions() != 1) {
1510472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can only " +
1511472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                    "be used with a one-dimensional array of primitives.", arrayClassDef.getClassType()));
1512472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        }
1513472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1514472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        int elementWidth;
1515472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        switch (arrayClassDef.getBaseElementClass().getClassType().charAt(0)) {
1516472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'Z':
1517472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'B':
1518472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                elementWidth = 1;
1519472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                break;
1520472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'C':
1521472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'S':
1522472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                elementWidth = 2;
1523472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                break;
1524472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'I':
1525472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'F':
1526472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                elementWidth = 4;
1527472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                break;
1528472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'J':
1529472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            case 'D':
1530472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                elementWidth = 8;
1531472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                break;
1532472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            default:
1533472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use fill-array-data with array type %s. It can " +
1534472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                        "only be used with a one-dimensional array of primitives.", arrayClassDef.getClassType()));
1535472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        }
1536472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1537472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1538b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com        int arrayDataAddressOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset();
1539b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com        int arrayDataCodeAddress = getInstructionAddress(analyzedInstruction) + arrayDataAddressOffset;
1540b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com        AnalyzedInstruction arrayDataInstruction = this.instructions.get(arrayDataCodeAddress);
1541472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        if (arrayDataInstruction == null || arrayDataInstruction.instruction.getFormat() != Format.ArrayData) {
1542472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Could not find an array data structure at code address 0x%x",
1543b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com                    arrayDataCodeAddress));
1544472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        }
1545472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1546472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        ArrayDataPseudoInstruction arrayDataPseudoInstruction =
1547472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                (ArrayDataPseudoInstruction)arrayDataInstruction.instruction;
1548472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1549472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        if (elementWidth != arrayDataPseudoInstruction.getElementWidth()) {
1550472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com            throw new ValidationException(String.format("The array data at code address 0x%x does not have the " +
1551472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                    "correct element width for array type %s. Expecting element width %d, got element width %d.",
1552b7e78115277e30c71e6e991da3f31c5a1403c634JesusFreke@JesusFreke.com                    arrayDataCodeAddress, arrayClassDef.getClassType(), elementWidth,
1553472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com                    arrayDataPseudoInstruction.getElementWidth()));
1554472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com        }
1555472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com    }
1556472d3ea58455ebf43d21819b2701fad98b5a0f9cJesusFreke@JesusFreke.com
1557ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleThrow(AnalyzedInstruction analyzedInstruction) {
1558ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA();
1559ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com
1560ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(register);
1561ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        assert registerType != null;
1562ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com
1563ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        if (registerType.category == RegisterType.Category.Null) {
1564ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com            return;
1565ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        }
1566ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com
1567ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        if (registerType.category != RegisterType.Category.Reference) {
1568ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use throw with non-reference type %s in register v%d",
1569ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com                    registerType.toString(), register));
1570ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        }
1571ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com
1572ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        assert registerType.type != null;
1573ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com
1574ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        if (!registerType.type.extendsClass(ClassPath.getClassDef("Ljava/lang/Throwable;"))) {
1575ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use throw with non-throwable type %s in register v%d",
1576ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com                    registerType.type.getClassType(), register));
1577ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com        }
1578ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com    }
1579ed140ca3e4fa66a03970affb3415a9fe2a924312JesusFreke@JesusFreke.com
1580ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleSwitch(AnalyzedInstruction analyzedInstruction, Format expectedSwitchDataFormat) {
1581cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com        int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA();
1582cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com        int switchCodeAddressOffset = ((OffsetInstruction)analyzedInstruction.instruction).getTargetAddressOffset();
1583cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com
158485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, register, Primitive32BitCategories);
1585cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com
1586cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com        int switchDataCodeAddress = this.getInstructionAddress(analyzedInstruction) + switchCodeAddressOffset;
1587cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com        AnalyzedInstruction switchDataAnalyzedInstruction = instructions.get(switchDataCodeAddress);
1588cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com
1589cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com        if (switchDataAnalyzedInstruction == null ||
1590cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com            switchDataAnalyzedInstruction.instruction.getFormat() != expectedSwitchDataFormat) {
1591cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com            throw new ValidationException(String.format("There is no %s structure at code address 0x%x",
1592cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com                    expectedSwitchDataFormat.name(), switchDataCodeAddress));
1593cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com        }
1594cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com    }
1595cda44f70cfebfae4875cd77455a171075aebac4dJesusFreke@JesusFreke.com
159685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private void handleFloatWideCmp(AnalyzedInstruction analyzedInstruction, EnumSet validCategories) {
1597f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
1598f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com
159985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), validCategories);
160085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), validCategories);
1601f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com
1602f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1603f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com                RegisterType.getRegisterType(RegisterType.Category.Byte, null));
1604f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com    }
1605f1a74cea19f10e9059e05f1cee6ae45baf118108JesusFreke@JesusFreke.com
1606ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIfEqNe(AnalyzedInstruction analyzedInstruction) {
1607aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
1608aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com
1609aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        RegisterType registerType1 = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA());
1610aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        assert registerType1 != null;
1611aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com
1612aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        RegisterType registerType2 = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
1613aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        assert registerType2 != null;
1614aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com
1615aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        if (!(
1616aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                (ReferenceCategories.contains(registerType1.category) &&
1617aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                ReferenceCategories.contains(registerType2.category))
1618aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                    ||
1619aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                (Primitive32BitCategories.contains(registerType1.category) &&
1620aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                Primitive32BitCategories.contains(registerType2.category))
1621aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com              )) {
1622aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com
1623aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com            throw new ValidationException(String.format("%s cannot be used on registers of dissimilar types %s and " +
1624aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                    "%s. They must both be a reference type or a primitive 32 bit type.",
1625aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com                    analyzedInstruction.instruction.opcode.name, registerType1.toString(), registerType2.toString()));
1626aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com        }
1627aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com    }
1628aba6bb0bbd1537a6df9614ee579773e4a8af70ffJesusFreke@JesusFreke.com
1629ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIf(AnalyzedInstruction analyzedInstruction) {
1630150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
1631150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com
163285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), Primitive32BitCategories);
163385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), Primitive32BitCategories);
1634150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com    }
1635150acd9db94f9886f6fc32e89acc15a1a5c1466fJesusFreke@JesusFreke.com
1636ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIfEqzNez(AnalyzedInstruction analyzedInstruction) {
1637cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
1638cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com
163985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(),
164085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                ReferenceAndPrimitive32BitCategories);
1641cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com    }
1642cb00252b6aed86cd3e7c426015cea83fcdbaa806JesusFreke@JesusFreke.com
1643ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIfz(AnalyzedInstruction analyzedInstruction) {
164416a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
164516a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com
164685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), Primitive32BitCategories);
164716a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com    }
164816a709ba046343bfefc15a6cdb0be38282126223JesusFreke@JesusFreke.com
1649ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handle32BitPrimitiveAget(AnalyzedInstruction analyzedInstruction,
1650b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                                             RegisterType.Category instructionCategory) {
1651b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
1652b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
165385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories);
1654b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1655b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
1656b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        assert arrayRegisterType != null;
1657b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1658b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        if (arrayRegisterType.category != RegisterType.Category.Null) {
1659b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            if (arrayRegisterType.category != RegisterType.Category.Reference) {
1660b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with non-array type %s",
1661b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString()));
1662b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            }
1663b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1664b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            assert arrayRegisterType.type != null;
1665b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
1666b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with non-array type %s",
1667b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType()));
1668b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            }
1669b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1670b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
1671b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
1672b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1673b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            if (arrayClassDef.getArrayDimensions() != 1) {
1674b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s",
1675b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType()));
1676b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            }
1677b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1678b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            RegisterType arrayBaseType =
1679b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                    RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType());
1680c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (!checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) {
1681b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " +
1682b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
1683b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
1684b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            }
1685b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        }
1686b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1687b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1688b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                RegisterType.getRegisterType(instructionCategory, null));
1689b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com    }
1690b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
1691ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleAgetWide(AnalyzedInstruction analyzedInstruction) {
1692c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
1693c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
169485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories);
1695c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1696c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com        RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
1697c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com        assert arrayRegisterType != null;
1698c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1699c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com        if (arrayRegisterType.category != RegisterType.Category.Null) {
1700c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            if (arrayRegisterType.category != RegisterType.Category.Reference) {
1701c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s",
1702c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        arrayRegisterType.category.toString()));
1703c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            }
1704c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1705c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            assert arrayRegisterType.type != null;
1706c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
1707c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s",
1708c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
1709c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            }
1710c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1711c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
1712c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
1713c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1714c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            if (arrayClassDef.getArrayDimensions() != 1) {
1715c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-wide with multi-dimensional array type %s",
1716c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
1717c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            }
1718c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1719c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            char arrayBaseType = arrayClassDef.getBaseElementClass().getClassType().charAt(0);
1720c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            if (arrayBaseType == 'J') {
172185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1722c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        RegisterType.getRegisterType(RegisterType.Category.LongLo, null));
1723c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            } else if (arrayBaseType == 'D') {
172485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1725c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        RegisterType.getRegisterType(RegisterType.Category.DoubleLo, null));
1726c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            } else {
1727c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-wide with array type %s. Incorrect " +
1728c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        "array type for the instruction.", arrayRegisterType.type.getClassType()));
1729c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com            }
1730c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com        } else {
173185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1732c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com                        RegisterType.getRegisterType(RegisterType.Category.LongLo, null));
1733c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com        }
1734c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com    }
1735c308b24b6261ea81497a69e6d4d7ef6319943b10JesusFreke@JesusFreke.com
1736ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleAgetObject(AnalyzedInstruction analyzedInstruction) {
1737461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
1738461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
173985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories);
1740461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1741461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com        RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
1742461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com        assert arrayRegisterType != null;
1743461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1744461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com        if (arrayRegisterType.category != RegisterType.Category.Null) {
1745461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            if (arrayRegisterType.category != RegisterType.Category.Reference) {
1746461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-object with non-array type %s",
1747461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                        arrayRegisterType.category.toString()));
1748461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            }
1749461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1750461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            assert arrayRegisterType.type != null;
1751461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
1752461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-object with non-array type %s",
1753461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
1754461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            }
1755461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1756461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
1757461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
1758461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1759461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            ClassPath.ClassDef elementClassDef = arrayClassDef.getImmediateElementClass();
1760461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            char elementTypePrefix = elementClassDef.getClassType().charAt(0);
1761461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            if (elementTypePrefix != 'L' && elementTypePrefix != '[') {
1762461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-object with array type %s. Incorrect " +
1763461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                        "array type for the instruction.", arrayRegisterType.type.getClassType()));
1764461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            }
1765461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1766461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1767461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                    RegisterType.getRegisterType(RegisterType.Category.Reference, elementClassDef));
1768461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com        } else {
1769461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com            setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
1770461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com                    RegisterType.getRegisterType(RegisterType.Category.Null, null));
1771461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com        }
1772461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com    }
1773461a797324f0377db6cf06f680dec894b6f91204JesusFreke@JesusFreke.com
1774ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handle32BitPrimitiveAput(AnalyzedInstruction analyzedInstruction,
1775c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                                             RegisterType.Category instructionCategory) {
1776c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
1777c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
177885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories);
1779c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1780c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA());
1781c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        assert sourceRegisterType != null;
1782c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null);
1783c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) {
1784c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with source register type %s.",
1785c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                    analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString()));
1786c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        }
1787c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1788c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1789c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
1790c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        assert arrayRegisterType != null;
1791c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1792c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        if (arrayRegisterType.category != RegisterType.Category.Null) {
1793c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            if (arrayRegisterType.category != RegisterType.Category.Reference) {
1794c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with non-array type %s",
1795c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, arrayRegisterType.category.toString()));
1796c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            }
1797c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1798c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            assert arrayRegisterType.type != null;
1799c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
1800c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with non-array type %s",
1801c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType()));
1802c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            }
1803c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1804c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
1805c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
1806c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1807c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            if (arrayClassDef.getArrayDimensions() != 1) {
1808c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with multi-dimensional array type %s",
1809c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, arrayRegisterType.type.getClassType()));
1810c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            }
1811c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1812c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            RegisterType arrayBaseType =
1813c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                    RegisterType.getRegisterTypeForType(arrayClassDef.getBaseElementClass().getClassType());
1814c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (!checkArrayFieldAssignment(arrayBaseType.category, instructionCategory)) {
1815c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with array type %s. Incorrect array type " +
1816c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
1817c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
181855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            }
181955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com        }
182055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com    }
182155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
1822ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleAputWide(AnalyzedInstruction analyzedInstruction) {
182355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
182455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
182585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories);
182685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), WideLowCategories);
182755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
182855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com        RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
182955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com        assert arrayRegisterType != null;
183055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
183155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com        if (arrayRegisterType.category != RegisterType.Category.Null) {
183255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            if (arrayRegisterType.category != RegisterType.Category.Reference) {
183355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aput-wide with non-array type %s",
183455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                        arrayRegisterType.category.toString()));
183555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            }
183655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
183755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            assert arrayRegisterType.type != null;
183855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
183955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aput-wide with non-array type %s",
184055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
184155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            }
184255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
184355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
184455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
184555d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
184655d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            if (arrayClassDef.getArrayDimensions() != 1) {
184755d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aput-wide with multi-dimensional array type %s",
184855d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
184955d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            }
185055d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com
185155d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            char arrayBaseType = arrayClassDef.getBaseElementClass().getClassType().charAt(0);
185255d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com            if (arrayBaseType != 'J' && arrayBaseType != 'D') {
185355d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aput-wide with array type %s. Incorrect " +
185455d43e36eb862bf86ceaf9c664789ce2c4d92af8JesusFreke@JesusFreke.com                        "array type for the instruction.", arrayRegisterType.type.getClassType()));
1855898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            }
1856898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        }
1857898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com    }
1858898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1859ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleAputObject(AnalyzedInstruction analyzedInstruction) {
1860898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
1861898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
186285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(), Primitive32BitCategories);
1863898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1864898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA());
1865898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        assert sourceRegisterType != null;
1866ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com
18676d11e9062dfaa27c7fa8719d9d9b4f58b0d5cfa0JesusFreke@JesusFreke.com        //TODO: ensure sourceRegisterType is a Reference type?
1868898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1869898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB());
1870898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        assert arrayRegisterType != null;
1871898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1872898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com        if (arrayRegisterType.category != RegisterType.Category.Null) {
1873898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            //don't check the source type against the array type, just make sure it is an array of reference types
1874898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1875898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            if (arrayRegisterType.category != RegisterType.Category.Reference) {
1876898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-object with non-array type %s",
1877898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com                        arrayRegisterType.category.toString()));
1878898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            }
1879898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1880898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            assert arrayRegisterType.type != null;
1881898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            if (arrayRegisterType.type.getClassType().charAt(0) != '[') {
1882898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-object with non-array type %s",
1883898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com                        arrayRegisterType.type.getClassType()));
1884898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            }
1885898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1886898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            assert arrayRegisterType.type instanceof ClassPath.ArrayClassDef;
1887898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            ClassPath.ArrayClassDef arrayClassDef = (ClassPath.ArrayClassDef)arrayRegisterType.type;
1888898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com
1889898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            ClassPath.ClassDef elementClassDef = arrayClassDef.getImmediateElementClass();
1890898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            char elementTypePrefix = elementClassDef.getClassType().charAt(0);
1891898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com            if (elementTypePrefix != 'L' && elementTypePrefix != '[') {
1892898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use aget-object with array type %s. Incorrect " +
1893898e750048326802a488623d1ebf475df9bca209JesusFreke@JesusFreke.com                        "array type for the instruction.", arrayRegisterType.type.getClassType()));
1894c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com            }
1895c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com        }
1896c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com    }
1897c849236be2031b02d66eac4149617fd8a83572b4JesusFreke@JesusFreke.com
1898ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handle32BitPrimitiveIget(AnalyzedInstruction analyzedInstruction,
18994f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com                                             RegisterType.Category instructionCategory) {
19004f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
19014f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
190285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
1903c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                ReferenceOrUninitThisCategories);
19044f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
19054f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        //TODO: check access
19064f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
19074f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
19084f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
19094f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
19104f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        if (objectRegisterType.category != RegisterType.Category.Null &&
19114f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) {
19124f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot access field %s through type %s",
19134f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com                    field.getFieldString(), objectRegisterType.type.getClassType()));
19144f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        }
19154f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
19164f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
19174f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
19184f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) {
19194f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
19204f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
19214f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com                        field.getFieldString()));
19224f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        }
19234f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
19244f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
19254f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com                RegisterType.getRegisterType(instructionCategory, null));
19264f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com    }
19274f84e8f9e9bf4c74cbb2fc083d16ecb4fe0ec501JesusFreke@JesusFreke.com
1928ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIgetWide(AnalyzedInstruction analyzedInstruction) {
19299d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
19309d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
193185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
1932c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                ReferenceOrUninitThisCategories);
19339d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
19349d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        //TODO: check access
19359d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
19369d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
19379d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
19389d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
19399d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        if (objectRegisterType.category != RegisterType.Category.Null &&
19409d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com            !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) {
19419d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot access field %s through type %s",
19429d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com                    field.getFieldString(), objectRegisterType.type.getClassType()));
19439d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        }
19449d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
19459d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
19469d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
194785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (!WideLowCategories.contains(fieldType.category)) {
19489d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
194985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    "for the instruction.", analyzedInstruction.instruction.opcode.name,
195085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    field.getFieldString()));
19519d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com        }
19529d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
195385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType);
19547a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com    }
19557a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
1956ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIgetObject(AnalyzedInstruction analyzedInstruction) {
19577a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
19587a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
195985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
1960c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                ReferenceOrUninitThisCategories);
19617a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
19627a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        //TODO: check access
19637a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
19647a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
19657a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
19667a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
19677a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        if (objectRegisterType.category != RegisterType.Category.Null &&
19687a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com            !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) {
19697a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot access field %s through type %s",
19707a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com                    field.getFieldString(), objectRegisterType.type.getClassType()));
19717a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        }
19727a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
19737a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
19747a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
19757a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        if (fieldType.category != RegisterType.Category.Reference) {
19767a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
19777a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
19787a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com                        field.getFieldString()));
19797a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        }
19807a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com
19817a58f2434a2d906735ce585064d0fa46003c460dJesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType);
19829d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com    }
19839d92fd3748eab8f23502dc11aff06e6e7d29d1f3JesusFreke@JesusFreke.com
1984ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handle32BitPrimitiveIput(AnalyzedInstruction analyzedInstruction,
19859971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com                                             RegisterType.Category instructionCategory) {
19869971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
19879971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
198885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
1989c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                ReferenceOrUninitThisCategories);
19909971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
19919971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA());
19929971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        assert sourceRegisterType != null;
19939971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
19949971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        //per CodeVerify.c in dalvik:
19959971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        //java generates synthetic functions that write byte values into boolean fields
19969971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        if (sourceRegisterType.category == RegisterType.Category.Byte &&
19979971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            instructionCategory == RegisterType.Category.Boolean) {
19989971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
19999971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            sourceRegisterType = RegisterType.getRegisterType(RegisterType.Category.Boolean, null);
20009971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        }
20019971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
20029971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null);
20039971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) {
20049971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with source register type %s.",
20059971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com                    analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString()));
20069971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        }
20079971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
20089971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
20099971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        //TODO: check access
20109971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
20119971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
20129971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
20139971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
20149971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        if (objectRegisterType.category != RegisterType.Category.Null &&
20159971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) {
20169971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot access field %s through type %s",
20179971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com                    field.getFieldString(), objectRegisterType.type.getClassType()));
20189971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        }
20199971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
20209971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
20219971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
20229971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) {
20239971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
20249971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
20259971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com                        field.getFieldString()));
20269971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com        }
20279971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com    }
20289971346f4ce431e103c900cfdc14299ea25c685dJesusFreke@JesusFreke.com
2029ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIputWide(AnalyzedInstruction analyzedInstruction) {
203092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
203192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
203285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
2033c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                ReferenceOrUninitThisCategories);
203492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
203585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), WideLowCategories);
203692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
203792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        //TODO: check access
203892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
203992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
204092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
204192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
204292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        if (objectRegisterType.category != RegisterType.Category.Null &&
204392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com                !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) {
204492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot access field %s through type %s",
204592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com                    field.getFieldString(), objectRegisterType.type.getClassType()));
204692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        }
204792616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
204892616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
204992616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
205092616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        if (!WideLowCategories.contains(fieldType.category)) {
205192616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
205292616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com                    "for the instruction.", analyzedInstruction.instruction.opcode.name,
205392616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com                    field.getFieldString()));
205492616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com        }
205592616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com    }
205692616c9f60a30b5d5ac423675db732cb2428ce79JesusFreke@JesusFreke.com
2057ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleIputObject(AnalyzedInstruction analyzedInstruction) {
205850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
205950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
206085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
2061c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                ReferenceOrUninitThisCategories);
206250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
2063c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(),
206485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                ReferenceCategories);
206550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
206650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        //TODO: check access
206750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
206850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
206950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
207050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
207150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        if (objectRegisterType.category != RegisterType.Category.Null &&
207250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            !objectRegisterType.type.extendsClass(ClassPath.getClassDef(field.getContainingClass()))) {
207350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot access field %s through type %s",
207450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com                    field.getFieldString(), objectRegisterType.type.getClassType()));
207550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        }
207650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
207750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
207850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
207950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        if (fieldType.category != RegisterType.Category.Reference) {
208050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
208150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
208250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com                        field.getFieldString()));
208350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        }
208450ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
208550ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        if (sourceRegisterType.category != RegisterType.Category.Null &&
208650ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            !fieldType.type.isInterface() &&
208750ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            !sourceRegisterType.type.extendsClass(fieldType.type)) {
208850ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
208950ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot store a value of type %s into a field of type %s",
209050ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com                    sourceRegisterType.type.getClassType(), fieldType.type.getClassType()));
209150ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com        }
209250ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com    }
209350ff6247416eff1a90edd1ebc222ac2cdc5c15cfJesusFreke@JesusFreke.com
2094ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handle32BitPrimitiveSget(AnalyzedInstruction analyzedInstruction,
2095052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com                                             RegisterType.Category instructionCategory) {
2096052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        //TODO: check access
2097052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
2098052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
2099052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
2100052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com
2101052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
2102052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com
2103052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) {
2104052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
2105052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
2106052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com                        field.getFieldString()));
2107052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        }
2108052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com
2109052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
2110052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com                RegisterType.getRegisterType(instructionCategory, null));
2111052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com    }
2112052f4890ab954dc8510230b2992904a1a66c5dccJesusFreke@JesusFreke.com
2113ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleSgetWide(AnalyzedInstruction analyzedInstruction) {
21142f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        //TODO: check access
21152f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
21162f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
21172f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
21182f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com
21192f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
21202f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com
21212f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com
21222f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        if (fieldType.category != RegisterType.Category.LongLo &&
21232f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com            fieldType.category != RegisterType.Category.DoubleLo) {
21242f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com
21252f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
21262f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com                    "for the instruction.", analyzedInstruction.instruction.opcode.name,
21272f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com                    field.getFieldString()));
21282f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com        }
21292f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com
213085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType);
21312d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com    }
21322d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com
2133ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleSgetObject(AnalyzedInstruction analyzedInstruction) {
21342d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        //TODO: check access
21352d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
21362d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
21372d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
21382d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com
21392d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
21402d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com
21412d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        if (fieldType.category != RegisterType.Category.Reference) {
21422d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
21432d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
21442d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com                        field.getFieldString()));
21452d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        }
21462d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com
21472d6d6eb22c86c79344b85ffe46fdd4268566bd0fJesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType);
21482f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com    }
21492f233fefd9d73af8fab4037a6f874b161b98b259JesusFreke@JesusFreke.com
2150ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handle32BitPrimitiveSput(AnalyzedInstruction analyzedInstruction,
21519d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com                                             RegisterType.Category instructionCategory) {
21529d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
21539d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21549d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        RegisterType sourceRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterA());
21559d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        assert sourceRegisterType != null;
21569d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21579d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        //per CodeVerify.c in dalvik:
21589d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        //java generates synthetic functions that write byte values into boolean fields
21599d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        if (sourceRegisterType.category == RegisterType.Category.Byte &&
21609d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            instructionCategory == RegisterType.Category.Boolean) {
21619d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21629d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            sourceRegisterType = RegisterType.getRegisterType(RegisterType.Category.Boolean, null);
21639d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        }
21649d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21659d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        RegisterType instructionRegisterType = RegisterType.getRegisterType(instructionCategory, null);
21669d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        if (!sourceRegisterType.canBeAssignedTo(instructionRegisterType)) {
21679d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with source register type %s.",
21689d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com                    analyzedInstruction.instruction.opcode.name, sourceRegisterType.toString()));
21699d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        }
21709d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21719d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        //TODO: check access
21729d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
21739d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
21749d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
21759d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21769d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
21779d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
21789d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        if (!checkArrayFieldAssignment(fieldType.category, instructionCategory)) {
21799d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
21809d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
21819d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com                        field.getFieldString()));
21829d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com        }
21839d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com    }
21849d45d563fedaddab6bbdd421b139fe91d2f15fc8JesusFreke@JesusFreke.com
2185ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleSputWide(AnalyzedInstruction analyzedInstruction) {
2186f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
2187f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com
2188f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com
218985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(), WideLowCategories);
2190f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com
2191f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        //TODO: check access
2192f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
2193f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
2194f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
2195f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com
2196f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
2197f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com
2198f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        if (!WideLowCategories.contains(fieldType.category)) {
2199f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
2200f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
2201f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com                        field.getFieldString()));
2202f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com        }
2203f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com    }
2204f08a9e1c2c130a5ed5923999fec0283f91b48a09JesusFreke@JesusFreke.com
2205ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleSputObject(AnalyzedInstruction analyzedInstruction) {
220651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction;
220751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
220885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(),
220985e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                ReferenceCategories);
221051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
221151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        //TODO: check access
221251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        Item referencedItem = ((InstructionWithReference)analyzedInstruction.instruction).getReferencedItem();
221351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        assert referencedItem instanceof FieldIdItem;
221451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        FieldIdItem field = (FieldIdItem)referencedItem;
221551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
221651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        RegisterType fieldType = RegisterType.getRegisterTypeForTypeIdItem(field.getFieldType());
221751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
221851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        if (fieldType.category != RegisterType.Category.Reference) {
221951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot use %s with field %s. Incorrect field type " +
222051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com                        "for the instruction.", analyzedInstruction.instruction.opcode.name,
222151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com                        field.getFieldString()));
222251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        }
222351cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
222451cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        if (sourceRegisterType.category != RegisterType.Category.Null &&
222551cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com            !fieldType.type.isInterface() &&
222651cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com            !sourceRegisterType.type.extendsClass(fieldType.type)) {
222751cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
222851cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Cannot store a value of type %s into a field of type %s",
222951cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com                    sourceRegisterType.type.getClassType(), fieldType.type.getClassType()));
223051cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com        }
223151cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com    }
223251cec00885cdc063ee27ee6b67680189be34f8f9JesusFreke@JesusFreke.com
2233ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleInvoke(AnalyzedInstruction analyzedInstruction, int invokeType) {
223489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction;
2235ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com        handleInvokeCommon(analyzedInstruction, false, invokeType, new Format35cRegisterIterator(instruction));
223689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    }
223789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
2238ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleInvokeRange(AnalyzedInstruction analyzedInstruction, int invokeType) {
223989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction;
2240ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com        handleInvokeCommon(analyzedInstruction, true, invokeType, new Format3rcRegisterIterator(instruction));
224189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    }
224289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
224389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    private static final int INVOKE_VIRTUAL = 0x01;
224489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    private static final int INVOKE_SUPER = 0x02;
224589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    private static final int INVOKE_DIRECT = 0x04;
224689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    private static final int INVOKE_INTERFACE = 0x08;
224789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    private static final int INVOKE_STATIC = 0x10;
224889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
2249ee7ca05c819845d013d0b15f9c75a92fea6a3b3dJesusFreke@JesusFreke.com    private void handleInvokeCommon(AnalyzedInstruction analyzedInstruction, boolean isRange, int invokeType,
225089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                                       RegisterIterator registers) {
225189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction;
225289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
225389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        //TODO: check access
225489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        //TODO: allow uninitialized reference if this in an <init> method
225589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
225689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        Item item = instruction.getReferencedItem();
225789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        assert item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM;
225889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        MethodIdItem methodIdItem = (MethodIdItem)item;
225989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
226089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        TypeIdItem methodClass = methodIdItem.getContainingClass();
226189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        boolean isInit = false;
226289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
226389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if (methodIdItem.getMethodName().getStringValue().charAt(0) == '<') {
226489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            if ((invokeType & INVOKE_DIRECT) != 0) {
226589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                isInit = true;
226689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            } else {
226789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot call constructor %s with %s",
226889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name));
226989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
227089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
227189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
227289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        ClassPath.ClassDef methodClassDef = ClassPath.getClassDef(methodClass);
227389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if ((invokeType & INVOKE_INTERFACE) != 0) {
227489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            if (!methodClassDef.isInterface()) {
227589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot call method %s with %s. %s is not an interface " +
227689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        "class.", methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name,
227789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        methodClassDef.getClassType()));
227889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
227989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        } else {
228089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            if (methodClassDef.isInterface()) {
228189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot call method %s with %s. %s is an interface class." +
228289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        " Use invoke-interface or invoke-interface/range instead.", methodIdItem.getMethodString(),
228389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, methodClassDef.getClassType()));
228489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
228589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
228689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
228789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if ((invokeType & INVOKE_SUPER) != 0) {
2288c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            ClassPath.ClassDef currentMethodClassDef = ClassPath.getClassDef(encodedMethod.method.getContainingClass());
2289c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (currentMethodClassDef.getSuperclass() == null) {
229089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot call method %s with %s. %s has no superclass",
229189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        methodIdItem.getMethodString(), analyzedInstruction.instruction.opcode.name,
229289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        methodClassDef.getSuperclass().getClassType()));
229389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
229489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
2295c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (!currentMethodClassDef.getSuperclass().extendsClass(methodClassDef)) {
2296c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot call method %s with %s. %s is not an ancestor " +
2297c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        "of the current class %s", methodIdItem.getMethodString(),
2298c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, methodClass.getTypeDescriptor(),
2299c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        encodedMethod.method.getContainingClass().getTypeDescriptor()));
2300c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            }
2301c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
2302c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (!currentMethodClassDef.getSuperclass().hasVirtualMethod(methodIdItem.getVirtualMethodString())) {
230389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot call method %s with %s. The superclass %s has" +
230489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        "no such method", methodIdItem.getMethodString(),
230589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        analyzedInstruction.instruction.opcode.name, methodClassDef.getSuperclass().getClassType()));
230689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
230789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
230889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
230989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        assert isRange || registers.getCount() <= 5;
231089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
231189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        TypeListItem typeListItem = methodIdItem.getPrototype().getParameters();
231289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        int methodParameterRegisterCount;
231389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if (typeListItem == null) {
231489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            methodParameterRegisterCount = 0;
231589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        } else {
231689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            methodParameterRegisterCount = typeListItem.getRegisterCount();
231789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
231889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
231989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if ((invokeType & INVOKE_STATIC) == 0) {
232089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            methodParameterRegisterCount++;
232189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
232289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
232389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if (methodParameterRegisterCount != registers.getCount()) {
232489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            throw new ValidationException(String.format("The number of registers does not match the number of " +
232589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    "parameters for method %s. Expecting %d registers, got %d.", methodIdItem.getMethodString(),
232689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    methodParameterRegisterCount + 1, registers.getCount()));
232789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
232889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
232989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        RegisterType objectRegisterType = null;
233089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        int objectRegister = 0;
233189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if ((invokeType & INVOKE_STATIC) == 0) {
233289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            objectRegister = registers.getRegister();
233389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            registers.moveNext();
233489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
233589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(objectRegister);
233689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            assert objectRegisterType != null;
2337c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (objectRegisterType.category == RegisterType.Category.UninitRef ||
2338c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    objectRegisterType.category == RegisterType.Category.UninitThis) {
2339c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
234089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                if (!isInit) {
234189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    throw new ValidationException(String.format("Cannot invoke non-<init> method %s on uninitialized " +
234289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            "reference type %s", methodIdItem.getMethodString(),
234389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            objectRegisterType.type.getClassType()));
234489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                }
234589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            } else if (objectRegisterType.category == RegisterType.Category.Reference) {
234689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                if (isInit) {
234789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    throw new ValidationException(String.format("Cannot invoke %s on initialized reference type %s",
234889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            methodIdItem.getMethodString(), objectRegisterType.type.getClassType()));
234989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                }
235089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            } else if (objectRegisterType.category == RegisterType.Category.Null) {
235189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                if (isInit) {
235289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    throw new ValidationException(String.format("Cannot invoke %s on a null reference",
235389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            methodIdItem.getMethodString()));
235489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                }
235589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
235689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            else {
235789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                throw new ValidationException(String.format("Cannot invoke %s on non-reference type %s",
235889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        methodIdItem.getMethodString(), objectRegisterType.toString()));
235989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
236089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
236189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            if (isInit) {
23627e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (objectRegisterType.type.getSuperclass() == methodClassDef) {
23637e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    if (!encodedMethod.method.getMethodName().getStringValue().equals("<init>")) {
236489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        throw new ValidationException(String.format("Cannot call %s on type %s. The object type must " +
236589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                                "match the method type exactly", methodIdItem.getMethodString(),
236689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                                objectRegisterType.type.getClassType()));
236789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    }
236889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                }
236989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
237089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
2371c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if ((invokeType & INVOKE_INTERFACE) == 0 && objectRegisterType.category != RegisterType.Category.Null &&
2372c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    !objectRegisterType.type.extendsClass(methodClassDef)) {
237389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
237489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com               throw new ValidationException(String.format("Cannot call method %s on an object of type %s, which " +
237589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                       "does not extend %s.", methodIdItem.getMethodString(), objectRegisterType.type.getClassType(),
237689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        methodClassDef.getClassType()));
237789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
237889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
237989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
23807e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        if (typeListItem != null) {
23817e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            List<TypeIdItem> parameterTypes = typeListItem.getTypes();
23827e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            int parameterTypeIndex = 0;
23837e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            while (!registers.pastEnd()) {
23847e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                assert parameterTypeIndex < parameterTypes.size();
23857e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                RegisterType parameterType =
23867e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        RegisterType.getRegisterTypeForTypeIdItem(parameterTypes.get(parameterTypeIndex));
238789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
23887e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                int register = registers.getRegister();
238989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
23907e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                RegisterType parameterRegisterType;
23917e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (WideLowCategories.contains(parameterType.category)) {
23927e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    parameterRegisterType = getAndCheckSourceRegister(analyzedInstruction, register, WideLowCategories);
239389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
23947e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    if (!registers.moveNext()) {
23957e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        throw new ValidationException(String.format("No 2nd register specified for wide register pair v%d",
23967e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                                parameterTypeIndex+1));
23977e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    }
23987e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    int nextRegister = registers.getRegister();
239989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
24007e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    if (nextRegister != register + 1) {
24017e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                        throw new ValidationException(String.format("Invalid wide register pair (v%d, v%d). Registers " +
24027e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                                "must be consecutive.", register, nextRegister));
24037e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    }
24047e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                } else {
24057e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    parameterRegisterType = analyzedInstruction.getPreInstructionRegisterType(register);
240689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                }
240789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
24087e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                assert parameterRegisterType != null;
240989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
24107e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                if (!parameterRegisterType.canBeAssignedTo(parameterType)) {
24117e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                    throw new ValidationException(
24127e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                            String.format("Invalid register type %s for parameter %d %s.",
24137e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                                    parameterRegisterType.toString(), parameterTypeIndex+1,
24147e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                                    parameterType.toString()));
24157e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                }
241689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
24177e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                parameterTypeIndex++;
24187e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                registers.moveNext();
24197e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            }
242089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
242189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
242289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
242389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        //TODO: need to ensure the "this" register is initialized, in a constructor method
242489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        if (isInit) {
242589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            setRegisterTypeAndPropagateChanges(analyzedInstruction, objectRegister,
242689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    RegisterType.getRegisterType(RegisterType.Category.Reference, objectRegisterType.type));
242789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
242889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            for (int i=0; i<analyzedInstruction.postRegisterMap.length; i++) {
242989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                RegisterType postInstructionRegisterType = analyzedInstruction.postRegisterMap[i];
243089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                if (postInstructionRegisterType.category == RegisterType.Category.Unknown) {
243189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    RegisterType preInstructionRegisterType =
243289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            analyzedInstruction.getMergedRegisterTypeFromPredecessors(i);
243389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
2434c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                    if (preInstructionRegisterType.category == RegisterType.Category.UninitRef ||
2435c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        preInstructionRegisterType.category == RegisterType.Category.UninitThis) {
2436c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
243789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        RegisterType registerType = null;
243889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        if (preInstructionRegisterType == objectRegisterType) {
243989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            registerType = analyzedInstruction.postRegisterMap[objectRegister];
244089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        } else {
244189e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                            registerType = preInstructionRegisterType;
244289e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        }
244389e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
244489e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                        setRegisterTypeAndPropagateChanges(analyzedInstruction, i, registerType);
244589e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                    }
244689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com                }
244789e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com            }
244889e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com        }
244989e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com    }
245089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
24511483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com    private void handleUnaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSourceCategories,
24521483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                            RegisterType.Category destRegisterCategory) {
24531483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
24541483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com
24551483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com        getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), validSourceCategories);
245689e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
24571483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
24581483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com                RegisterType.getRegisterType(destRegisterCategory, null));
24591483cc8e6879d0de625adbcbffd2df42131a90c1JesusFreke@JesusFreke.com    }
246089e1413ef3d2438f7126b2c55f6f57d62361e775JesusFreke@JesusFreke.com
2461195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com    private void handleBinaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSource1Categories,
2462195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                                EnumSet validSource2Categories, RegisterType.Category destRegisterCategory,
2463195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                                boolean checkForBoolean) {
2464195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com        ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction;
2465195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com
2466195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com        RegisterType source1RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
2467195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                validSource1Categories);
2468195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com        RegisterType source2RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterC(),
2469195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                validSource2Categories);
2470195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com
2471195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com        if (checkForBoolean) {
2472195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            if (BooleanCategories.contains(source1RegisterType.category) &&
2473195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                BooleanCategories.contains(source2RegisterType.category)) {
2474195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com
2475195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                destRegisterCategory = RegisterType.Category.Boolean;
2476195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com            }
2477195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com        }
2478195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com
2479195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
2480195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com                RegisterType.getRegisterType(destRegisterCategory, null));
2481195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com    }
2482195e1a1071cce71fe6dd0edd4d6d23090dd0de14JesusFreke@JesusFreke.com
2483122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com    private void handleBinary2AddrOp(AnalyzedInstruction analyzedInstruction, EnumSet validSource1Categories,
2484122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                                EnumSet validSource2Categories, RegisterType.Category destRegisterCategory,
2485122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                                boolean checkForBoolean) {
2486122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
2487122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com
2488122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com        RegisterType source1RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterA(),
2489122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                validSource1Categories);
2490122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com        RegisterType source2RegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
2491122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                validSource2Categories);
2492122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com
2493122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com        if (checkForBoolean) {
2494122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            if (BooleanCategories.contains(source1RegisterType.category) &&
2495122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                BooleanCategories.contains(source2RegisterType.category)) {
2496122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com
2497122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                destRegisterCategory = RegisterType.Category.Boolean;
2498122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com            }
2499122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com        }
2500122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com
2501122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
2502122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com                RegisterType.getRegisterType(destRegisterCategory, null));
2503122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com    }
2504122eba5cecf44f6c819854e204779c83124abdf8JesusFreke@JesusFreke.com
2505caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com    private void handleLiteralBinaryOp(AnalyzedInstruction analyzedInstruction, EnumSet validSourceCategories,
2506caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                                RegisterType.Category destRegisterCategory, boolean checkForBoolean) {
2507caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
2508caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2509caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
2510caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                validSourceCategories);
2511caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2512caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        if (checkForBoolean) {
2513caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            if (BooleanCategories.contains(sourceRegisterType.category)) {
2514caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                long literal = ((LiteralInstruction)analyzedInstruction.instruction).getLiteral();
2515caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                if (literal == 0 || literal == 1) {
2516caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    destRegisterCategory = RegisterType.Category.Boolean;
2517caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                }
2518caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            }
2519caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        }
2520caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2521caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction,
2522caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                RegisterType.getRegisterType(destRegisterCategory, null));
2523caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com    }
2524caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2525caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com    private RegisterType.Category getDestTypeForLiteralShiftRight(AnalyzedInstruction analyzedInstruction,
2526caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                                                                  boolean signedShift) {
2527caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction;
2528caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2529caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        RegisterType sourceRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(),
2530caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                Primitive32BitCategories);
2531caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        long literalShift = ((LiteralInstruction)analyzedInstruction.instruction).getLiteral();
2532caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2533caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        if (literalShift == 0) {
2534caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            return sourceRegisterType.category;
2535caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        }
2536caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2537caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        RegisterType.Category destRegisterCategory;
2538caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        if (!signedShift) {
2539caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            destRegisterCategory = RegisterType.Category.Integer;
2540caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        } else {
2541caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            destRegisterCategory = sourceRegisterType.category;
2542caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        }
2543caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2544caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        if (literalShift >= 32) {
2545caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            //TODO: add warning
2546caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            return destRegisterCategory;
2547caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        }
2548caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2549caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        switch (sourceRegisterType.category) {
2550caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Integer:
2551caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Float:
2552caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                if (!signedShift) {
2553caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    if (literalShift > 24) {
2554caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        return RegisterType.Category.PosByte;
2555caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    }
2556caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    if (literalShift >= 16) {
2557caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        return RegisterType.Category.Char;
2558caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    }
2559caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                } else {
2560caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    if (literalShift >= 24) {
2561caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        return RegisterType.Category.Byte;
2562caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    }
2563caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    if (literalShift >= 16) {
2564caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                        return RegisterType.Category.Short;
2565caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    }
2566caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                }
2567caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                break;
2568caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Short:
2569caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                if (signedShift && literalShift >= 8) {
2570caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    return RegisterType.Category.Byte;
2571caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                }
2572caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                break;
2573caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case PosShort:
2574caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                if (literalShift >= 8) {
2575caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    return RegisterType.Category.PosByte;
2576caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                }
2577caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                break;
2578caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Char:
2579caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                if (literalShift > 8) {
2580caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                    return RegisterType.Category.PosByte;
2581caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                }
2582caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                break;
2583caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Byte:
2584caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                break;
2585caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case PosByte:
2586caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return RegisterType.Category.PosByte;
2587caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Null:
2588caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case One:
2589caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            case Boolean:
2590caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                return RegisterType.Category.Null;
2591caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com            default:
2592caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com                assert false;
2593caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        }
2594caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2595caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com        return destRegisterCategory;
2596caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com    }
2597caea37a7d2ad74f884111ee7420e7b37b9417afdJesusFreke@JesusFreke.com
2598b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com    private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory,
2599b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com                                                  RegisterType.Category instructionCategory) {
2600b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        if (arrayFieldCategory == instructionCategory) {
2601b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            return true;
2602b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        }
2603b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
2604b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        if ((arrayFieldCategory == RegisterType.Category.Integer &&
2605b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com             instructionCategory == RegisterType.Category.Float) ||
2606b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            (arrayFieldCategory == RegisterType.Category.Float &&
2607b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com             instructionCategory == RegisterType.Category.Integer)) {
2608b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com            return true;
2609b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        }
2610b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com        return false;
2611b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com    }
2612b2397452907c28b0743bbbcdf9fa6b2a8208aeabJesusFreke@JesusFreke.com
261385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private static RegisterType getAndCheckSourceRegister(AnalyzedInstruction analyzedInstruction, int registerNumber,
261485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                                            EnumSet validCategories) {
261585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        assert registerNumber >= 0 && registerNumber < analyzedInstruction.postRegisterMap.length;
2616fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
261785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNumber);
261885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        assert registerType != null;
2619fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
262085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        checkRegister(registerType, registerNumber, validCategories);
2621fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
262285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (validCategories == WideLowCategories) {
262385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            checkRegister(registerType, registerNumber, WideLowCategories);
262485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            checkWidePair(registerNumber, analyzedInstruction);
2625fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
262685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            RegisterType secondRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNumber + 1);
262785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            assert secondRegisterType != null;
262885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            checkRegister(secondRegisterType, registerNumber+1, WideHighCategories);
2629fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
2630fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
263185e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        return registerType;
263285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    }
2633fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com
263485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private static void checkRegister(RegisterType registerType, int registerNumber, EnumSet validCategories) {
263585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (!validCategories.contains(registerType.category)) {
263685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            //TODO: add expected categories to error message
263785e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("Invalid register type for register v%d. Expecting one of: " +
263885e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    "but got %s", registerNumber, registerType.toString()));
2639fffb29fd9d67ba1396bd2999de4f0d9a44b79837JesusFreke@JesusFreke.com        }
264085e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    }
2641d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com
264285e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com    private static void checkWidePair(int registerNumber, AnalyzedInstruction analyzedInstruction) {
264385e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        if (registerNumber + 1 >= analyzedInstruction.postRegisterMap.length) {
264485e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com            throw new ValidationException(String.format("v%d is the last register and not a valid wide register " +
264585e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com                    "pair.", registerNumber));
264685e17ca30a336e12592911afe666191947ec3697JesusFreke@JesusFreke.com        }
2647d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com    }
2648d27ca7f7a61cfbe60e1c490bf645257d7d59fd39JesusFreke@JesusFreke.com}
2649