MethodDefinition.java revision 10a95181115741071ae23911413a3f731047621c
136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com/*
236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * [The "BSD licence"]
300fc68adf2e39aeb9fed35293f2576bbe729ec4bJesusFreke@JesusFreke.com * Copyright (c) 2010 Ben Gruver (JesusFreke)
436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * All rights reserved.
536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com *
636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * Redistribution and use in source and binary forms, with or without
736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * modification, are permitted provided that the following conditions
836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * are met:
936836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 1. Redistributions of source code must retain the above copyright
1036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer.
1136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 2. Redistributions in binary form must reproduce the above copyright
1236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer in the
1336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com *    documentation and/or other materials provided with the distribution.
1436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 3. The name of the author may not be used to endorse or promote products
1536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com *    derived from this software without specific prior written permission.
1636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com *
1736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1936836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com */
2836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
296ef13753e78bb7abc7e7683d5e533c3395d4a9b6JesusFreke@JesusFreke.compackage org.jf.baksmali.Adaptors;
3036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
315f50a1a8b32b8fa81916c7f2d5b3c2d1b266995fJesusFreke@JesusFreke.comimport org.jf.baksmali.Adaptors.Format.*;
325b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.comimport org.jf.baksmali.baksmali;
331c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.comimport org.jf.baksmali.main;
34fa07a1972e3cff56d5615c18a8797ff58fc9f739JesusFreke@JesusFreke.comimport org.jf.dexlib.*;
351c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.comimport org.jf.dexlib.Code.*;
367e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Analysis.AnalyzedInstruction;
377e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Analysis.MethodAnalyzer;
387e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Analysis.RegisterType;
39c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Analysis.ValidationException;
400c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.Format;
41cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.comimport org.jf.dexlib.Debug.DebugInstructionIterator;
42bf4ca730cc857f76ee703e9efa73ad3e408c6c37JesusFreke@JesusFreke.comimport org.jf.dexlib.Util.AccessFlags;
437ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.comimport org.antlr.stringtemplate.StringTemplateGroup;
447ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.comimport org.antlr.stringtemplate.StringTemplate;
4510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.ExceptionWithContext;
462bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.Hex;
47b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.SparseIntArray;
4836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
499bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.comimport java.util.*;
5036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
5136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.compublic class MethodDefinition {
52b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private final StringTemplateGroup stg;
53b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private final ClassDataItem.EncodedMethod encodedMethod;
547e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com    private final MethodAnalyzer methodAnalyzer;
55b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
56b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private final LabelCache labelCache = new LabelCache();
57b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
58b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private final SparseIntArray packedSwitchMap;
59b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private final SparseIntArray sparseSwitchMap;
60b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private final SparseIntArray instructionMap;
61b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
621c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private final int registerCount;
631c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
64b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    public MethodDefinition(StringTemplateGroup stg, ClassDataItem.EncodedMethod encodedMethod) {
6510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
6610a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
6710a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com        try {
6810a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com            this.stg = stg;
6910a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com            this.encodedMethod = encodedMethod;
7010a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
7110a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com            //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh.
7210a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
7310a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com            if (encodedMethod.codeItem != null) {
7410a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex);
7510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
7610a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
7710a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                packedSwitchMap = new SparseIntArray(1);
7810a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                sparseSwitchMap = new SparseIntArray(1);
7910a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                instructionMap = new SparseIntArray(instructions.size());
8010a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
8110a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                registerCount = encodedMethod.codeItem.getRegisterCount();
8210a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com
8310a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                int currentCodeAddress = 0;
8410a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                for (int i=0; i<instructions.size(); i++) {
8510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    AnalyzedInstruction instruction = instructions.get(i);
8610a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    if (instruction.getInstruction().opcode == Opcode.PACKED_SWITCH) {
8710a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                        packedSwitchMap.append(
8810a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                                currentCodeAddress + ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
8910a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                                currentCodeAddress);
9010a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    } else if (instruction.getInstruction().opcode == Opcode.SPARSE_SWITCH) {
9110a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                        sparseSwitchMap.append(
9210a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                                currentCodeAddress + ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(),
9310a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                                currentCodeAddress);
9410a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    }
9510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    instructionMap.append(currentCodeAddress, i);
9610a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
97b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                }
9810a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com            } else {
9910a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                packedSwitchMap = null;
10010a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                sparseSwitchMap = null;
10110a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                instructionMap = null;
10210a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                methodAnalyzer = null;
10310a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                registerCount = 0;
104b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            }
10510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com        }catch (Exception ex) {
10610a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com            throw ExceptionWithContext.withContext(ex, String.format("Error while processing method %s",
10710a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com                    encodedMethod.method.getMethodString()));
108b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        }
109b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
110b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
111b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    public StringTemplate createTemplate(AnnotationSetItem annotationSet,
112b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                                AnnotationSetRefList parameterAnnotations) {
11336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
1147ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        CodeItem codeItem = encodedMethod.codeItem;
11536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
1167ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        StringTemplate template = stg.getInstanceOf("method");
11736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
1187ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        template.setAttribute("AccessFlags", getAccessFlags(encodedMethod));
1197ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        template.setAttribute("MethodName", encodedMethod.method.getMethodName().getStringValue());
1207ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        template.setAttribute("Prototype", encodedMethod.method.getPrototype().getPrototypeString());
1217ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        template.setAttribute("HasCode", codeItem != null);
122ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com        template.setAttribute("RegistersDirective", baksmali.useLocalsDirective?".locals":".registers");
123ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com        template.setAttribute("RegisterCount", codeItem==null?"0":Integer.toString(getRegisterCount(encodedMethod)));
1247ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        template.setAttribute("Parameters", getParameters(stg, codeItem, parameterAnnotations));
1257ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        template.setAttribute("Annotations", getAnnotations(stg, annotationSet));
126b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        template.setAttribute("MethodItems", getMethodItems());
12736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
1285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return template;
12936836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com    }
13036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
131ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com    private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod)
132ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com    {
133ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com        int totalRegisters = encodedMethod.codeItem.getRegisterCount();
134ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com        if (baksmali.useLocalsDirective) {
135ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com            int parameterRegisters = encodedMethod.method.getPrototype().getParameterRegisterCount();
136ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com            if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
137ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com                parameterRegisters++;
138ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com            }
139ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com            return totalRegisters - parameterRegisters;
140ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com        }
141ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com        return totalRegisters;
142ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com    }
143ff80035f438dd2a70330931bb87e37bb8b42f9e0JesusFreke@JesusFreke.com
1447ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com    private static List<String> getAccessFlags(ClassDataItem.EncodedMethod encodedMethod) {
1457ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        List<String> accessFlags = new ArrayList<String>();
14636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com
1477ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) {
1487ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com            accessFlags.add(accessFlag.toString());
14936836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com        }
1505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1517ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        return accessFlags;
152fa07a1972e3cff56d5615c18a8797ff58fc9f739JesusFreke@JesusFreke.com    }
153fa07a1972e3cff56d5615c18a8797ff58fc9f739JesusFreke@JesusFreke.com
1547ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com    private static List<StringTemplate> getParameters(StringTemplateGroup stg, CodeItem codeItem,
1557ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com                                                               AnnotationSetRefList parameterAnnotations) {
1563c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        DebugInfoItem debugInfoItem = null;
157630f5dc2dcaa811410ae1f9209e377d2e89d8e5cJesusFreke@JesusFreke.com        if (baksmali.outputDebugInfo && codeItem != null) {
1583c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            debugInfoItem = codeItem.getDebugInfo();
1593c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        }
1603c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1613c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        int parameterCount = 0;
1623c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1633c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        List<AnnotationSetItem> annotations = new ArrayList<AnnotationSetItem>();
1643c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        if (parameterAnnotations != null) {
165cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com            AnnotationSetItem[] _annotations = parameterAnnotations.getAnnotationSets();
1663c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            if (_annotations != null) {
167cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com                annotations.addAll(Arrays.asList(_annotations));
1683c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            }
1693c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1703c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            parameterCount = annotations.size();
1713c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        }
1723c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1733c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        List<String> parameterNames = new ArrayList<String>();
1743c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        if (debugInfoItem != null) {
175cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com            StringIdItem[] _parameterNames = debugInfoItem.getParameterNames();
1763c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            if (_parameterNames != null) {
177cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com                for (StringIdItem parameterName: _parameterNames) {
1782700dc281c1af60351fb3f4f6d423c90582904e4JesusFreke@JesusFreke.com                    parameterNames.add(parameterName==null?null:parameterName.getStringValue());
179cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com                }
1803c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            }
1813c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1823c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            if (parameterCount < parameterNames.size()) {
1833c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com                parameterCount = parameterNames.size();
1843c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            }
1853c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        }
1863c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1877ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        List<StringTemplate> parameters = new ArrayList<StringTemplate>();
1883c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        for (int i=0; i<parameterCount; i++) {
1893c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            AnnotationSetItem annotationSet = null;
1903c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            if (i < annotations.size()) {
1913c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com                annotationSet = annotations.get(i);
1923c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            }
1933c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1943c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            String parameterName = null;
1953c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            if (i < parameterNames.size()) {
1963c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com                parameterName = parameterNames.get(i);
1973c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            }
1983c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
1997d9b1b10f03035153829553ae372947b75e17f70JesusFreke@JesusFreke.com            parameters.add(ParameterAdaptor.createTemplate(stg, parameterName, annotationSet));
2003c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        }
2013c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
2027ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        return parameters;
2033c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com    }
2043c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
205b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    public LabelCache getLabelCache() {
206b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        return labelCache;
207b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
208b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
209c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    public ValidationException getValidationException() {
210c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        if (methodAnalyzer == null) {
211c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            return null;
212c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        }
213c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
214c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com        return methodAnalyzer.getValidationException();
215c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com    }
216c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
217b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    public int getPackedSwitchBaseAddress(int packedSwitchDataAddress) {
218b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1);
219b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
220b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        if (packedSwitchBaseAddress == -1) {
221b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            throw new RuntimeException("Could not find the packed switch statement corresponding to the packed " +
222b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    "switch data at address " + packedSwitchDataAddress);
223b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        }
224b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
225b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        return packedSwitchBaseAddress;
226b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
227b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
228b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    public int getSparseSwitchBaseAddress(int sparseSwitchDataAddress) {
229b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1);
230b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
231b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        if (sparseSwitchBaseAddress == -1) {
232b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            throw new RuntimeException("Could not find the sparse switch statement corresponding to the sparse " +
233b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    "switch data at address " + sparseSwitchDataAddress);
234b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        }
235b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
236b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        return sparseSwitchBaseAddress;
237b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
238b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
2397ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com    private static List<StringTemplate> getAnnotations(StringTemplateGroup stg, AnnotationSetItem annotationSet) {
2407ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        if (annotationSet == null) {
2413c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com            return null;
2423c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com        }
2433c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
2447ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        List<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>();
245cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com
2467ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        for (AnnotationItem annotationItem: annotationSet.getAnnotations()) {
2477d9b1b10f03035153829553ae372947b75e17f70JesusFreke@JesusFreke.com            annotationAdaptors.add(AnnotationAdaptor.createTemplate(stg, annotationItem));
2487ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        }
2497ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        return annotationAdaptors;
2503c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com    }
251ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com
252b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private List<MethodItem> getMethodItems() {
2537ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        List<MethodItem> methodItems = new ArrayList<MethodItem>();
2549bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com
255b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        if (encodedMethod.codeItem == null) {
256b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            return methodItems;
257630f5dc2dcaa811410ae1f9209e377d2e89d8e5cJesusFreke@JesusFreke.com        }
2589bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com
2597bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com        if (baksmali.registerInfo != 0 || baksmali.deodex || baksmali.verify) {
260ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            methodAnalyzer.analyze();
261c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com
262c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            ValidationException validationException = methodAnalyzer.getValidationException();
263c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            if (validationException != null) {
2641c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                methodItems.add(new CommentMethodItem(stg,
2651c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        String.format("ValidationException: %s" ,validationException.getMessage()),
266c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com                        validationException.getCodeAddress(), Integer.MIN_VALUE));
2677bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com            } else if (baksmali.verify) {
2687bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                methodAnalyzer.verify();
2697bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com
2707bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                validationException = methodAnalyzer.getValidationException();
2717bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                if (validationException != null) {
2727bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                    methodItems.add(new CommentMethodItem(stg,
2737bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                            String.format("ValidationException: %s" ,validationException.getMessage()),
2747bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                            validationException.getCodeAddress(), Integer.MIN_VALUE));
2757bb8ace93bb02750a95d3a68fe99153980abdee8JesusFreke@JesusFreke.com                }
276c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com            }
2777e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        }
278ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions();
279ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com
2800c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        AnalyzedInstruction lastInstruction = null;
2810c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com
282ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        for (int i=instructions.size()-1; i>=0; i--) {
283ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            AnalyzedInstruction instruction = instructions.get(i);
2840c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com
2850c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            if (!instruction.isDead()) {
2860c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                lastInstruction = instruction;
2870c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                break;
2880c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            }
2890c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        }
2900c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com
2911c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        BitSet printPreRegister = new BitSet(registerCount);
2921c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        BitSet printPostRegister = new BitSet(registerCount);
2931c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
294b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        int currentCodeAddress = 0;
295ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        for (int i=0; i<instructions.size(); i++) {
296ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            AnalyzedInstruction instruction = instructions.get(i);
297ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com
2980c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
2990c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    encodedMethod.codeItem, currentCodeAddress, stg, instruction.getInstruction(),
3000c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    instruction == lastInstruction);
3010c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com
3020c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            if (instruction.isDead()) {
3030c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                methodItems.add(new CommentedOutMethodItem(stg, methodItem));
3040c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            } else {
3050c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                methodItems.add(methodItem);
3060c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            }
3070c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com
3080c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            if (instruction.getInstruction().getFormat() == Format.UnresolvedNullReference) {
3090c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                methodItems.add(new CommentedOutMethodItem(stg, InstructionMethodItemFactory.makeInstructionFormatMethodItem(this,
3100c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        encodedMethod.codeItem, currentCodeAddress, stg, instruction.getOriginalInstruction(), false)));
3110c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            }
3127ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com
313ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            if (i != instructions.size() - 1) {
314b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                methodItems.add(new BlankMethodItem(stg, currentCodeAddress));
315b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            }
316e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
3172bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com            if (baksmali.addCodeOffsets) {
3182bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com                methodItems.add(new CommentMethodItem(stg, String.format("@%x", currentCodeAddress),
3192bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com                        currentCodeAddress, -1000));
3202bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com            }
3212bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com
3220c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) {
3231c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                printPreRegister.clear();
3241c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                printPostRegister.clear();
3251c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
3261c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                if ((baksmali.registerInfo & main.ALL) != 0) {
3271c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPreRegister.set(0, registerCount);
3281c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPostRegister.set(0, registerCount);
3291c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                } else {
3301c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    if ((baksmali.registerInfo & main.ALLPRE) != 0) {
3311c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        printPreRegister.set(0, registerCount);
3321c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    } else {
3331c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        if ((baksmali.registerInfo & main.ARGS) != 0) {
3341c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                            addArgsRegs(printPreRegister, instruction);
3351c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        }
3361c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        if ((baksmali.registerInfo & main.MERGE) != 0) {
337ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com                            addMergeRegs(printPreRegister, instruction);
3381c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        } else if ((baksmali.registerInfo & main.FULLMERGE) != 0 &&
3391c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                                (i == 0 || instruction.isBeginningInstruction())) {
3401c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                            addParamRegs(printPreRegister);
3411c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        }
3421c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    }
3431c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
3441c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    if ((baksmali.registerInfo & main.ALLPOST) != 0) {
3451c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        printPostRegister.set(0, registerCount);
3461c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    } else if ((baksmali.registerInfo & main.DEST) != 0) {
3471c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                        addDestRegs(printPostRegister, instruction);
3481c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    }
3497e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                }
3507e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
3511c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                if ((baksmali.registerInfo & main.FULLMERGE) != 0) {
352ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com                    addFullMergeRegs(printPreRegister, methodItems, methodAnalyzer, instruction, currentCodeAddress);
3531c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                }
3541c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
3551c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                if (!printPreRegister.isEmpty()) {
3560c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    String comment = getPreInstructionRegisterString(instruction, printPreRegister);
3570c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    if (comment != null && comment.length() > 0) {
3580c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        methodItems.add(new CommentMethodItem(stg, comment, currentCodeAddress, 99.9));
3590c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    }
3601c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                }
3611c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
3621c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                if (!printPostRegister.isEmpty()) {
3630c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    String comment = getPostInstructionRegisterString(instruction, printPostRegister);
3640c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    if (comment != null && comment.length() > 0) {
3650c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        methodItems.add(new CommentMethodItem(stg, comment, currentCodeAddress, 100.1));
3660c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    }
3671c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                }
3681c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
3697e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
3700c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress);
371b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        }
3729bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com
373b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        addTries(methodItems);
374b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        addDebugInfo(methodItems);
3759bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com
376b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        if (baksmali.useSequentialLabels) {
377b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            setLabelSequentialNumbers();
3787ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com        }
3799bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com
3805b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com
381b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        for (LabelMethodItem labelMethodItem: labelCache.getLabels()) {
382b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            if (labelMethodItem.isCommentedOut()) {
383b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                methodItems.add(new CommentedOutMethodItem(stg, labelMethodItem));
384b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            } else {
385b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                methodItems.add(labelMethodItem);
386b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            }
387b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        }
3885b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com
389b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        Collections.sort(methodItems);
3905b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com
391b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        return methodItems;
392b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
393e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com
3941c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private void addArgsRegs(BitSet printPreRegister, AnalyzedInstruction analyzedInstruction) {
3950c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        if (analyzedInstruction.getInstruction() instanceof RegisterRangeInstruction) {
3960c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction();
3971c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
3981c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getStartRegister(),
3991c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    instruction.getStartRegister() + instruction.getRegCount());
4000c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        } else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) {
4010c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction();
4021c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            int regCount = instruction.getRegCount();
4031c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            switch (regCount) {
4041c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                case 5:
4051c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPreRegister.set(instruction.getRegisterA());
4061c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    //fall through
4071c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                case 4:
4081c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPreRegister.set(instruction.getRegisterG());
4091c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    //fall through
4101c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                case 3:
4111c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPreRegister.set(instruction.getRegisterF());
4121c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    //fall through
4131c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                case 2:
4141c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPreRegister.set(instruction.getRegisterE());
4151c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    //fall through
4161c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                case 1:
4171c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    printPreRegister.set(instruction.getRegisterD());
4181c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
4190c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        } else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) {
4200c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction();
4211c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getRegisterA());
4221c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getRegisterB());
4231c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getRegisterC());
4240c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        } else if (analyzedInstruction.getInstruction() instanceof TwoRegisterInstruction) {
4250c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction();
4261c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getRegisterA());
4271c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getRegisterB());
4280c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com        } else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) {
4290c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction();
4301c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.set(instruction.getRegisterA());
4311c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        }
4321c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    }
4331c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4341c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private void addFullMergeRegs(BitSet printPreRegister, List<MethodItem> methodItems, MethodAnalyzer methodAnalyzer,
435ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com                                  AnalyzedInstruction instruction, int currentCodeAddress) {
4361c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        if (instruction.getPredecessorCount() <= 1) {
4371c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            return;
4381c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        }
4391c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4401c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        StringBuffer sb = new StringBuffer();
4411c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4421c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        for (int registerNum=0; registerNum<registerCount; registerNum++) {
4431c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.setLength(0);
4441c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append(RegisterFormatter.formatRegister(encodedMethod.codeItem, registerNum));
4451c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append('=');
4461c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append(instruction.getPreInstructionRegisterType(registerNum));
4471c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append(":merge{");
4481c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4490c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com            RegisterType mergedRegisterType = null;
4501c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            boolean addRegister = false;
4511c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4521c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            boolean first = true;
4531c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            for (AnalyzedInstruction predecessor: instruction.getPredecessors()) {
4541c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum);
4551c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4561c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                if (!first) {
4570c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    if (!addRegister) {
4580c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        sb.append(',');
4590c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        if (mergedRegisterType != predecessorRegisterType) {
4600c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                            addRegister = true;
4610c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        }
4620c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                        mergedRegisterType = mergedRegisterType.merge(predecessorRegisterType);
4631c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    }
4640c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                } else {
4650c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                    mergedRegisterType = predecessorRegisterType;
4661c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                }
4671c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4681c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                if (predecessor.getInstructionIndex() == -1) {
4691c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    //the fake "StartOfMethod" instruction
4701c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    sb.append("Start:");
4711c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                } else {
4721c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    sb.append("0x");
4731c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    sb.append(Integer.toHexString(methodAnalyzer.getInstructionAddress(predecessor)));
4741c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    sb.append(':');
4751c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                }
4760c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com                sb.append(predecessorRegisterType.toString());
4771c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                first = false;
4781c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
4791c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4801c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            if (!addRegister) {
4811c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                continue;
4821c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
4831c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4841c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append("}");
4851c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
4861c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            methodItems.add(new CommentMethodItem(stg, sb.toString(),  currentCodeAddress, 99.8));
4871c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            printPreRegister.clear(registerNum);
4881c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        }
4891c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    }
4901c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
491ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com    private void addMergeRegs(BitSet printPreRegister, AnalyzedInstruction instruction) {
492ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        if (instruction.isBeginningInstruction()) {
4931c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            addParamRegs(printPreRegister);
494ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        }
4951c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
496ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        if (instruction.getPredecessorCount() <= 1) {
497ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            //in the common case of an instruction that only has a single predecessor which is the previous
498ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            //instruction, the pre-instruction registers will always match the previous instruction's
499ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            //post-instruction registers
500ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            return;
501ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        }
5021c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
503ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com        for (int registerNum=0; registerNum<registerCount; registerNum++) {
504ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            RegisterType mergedRegisterType = instruction.getPreInstructionRegisterType(registerNum);
5051c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
506ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com            for (AnalyzedInstruction predecessor: instruction.getPredecessors()) {
507ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com                if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) {
508ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com                    printPreRegister.set(registerNum);
509ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com                    continue;
5101c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                }
5111c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
5121c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        }
5131c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    }
5141c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5151c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private void addParamRegs(BitSet printPreRegister) {
5161c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        int registerCount = encodedMethod.codeItem.getRegisterCount();
5171c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5181c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount();
5191c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) {
5201c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            parameterRegisterCount++;
5211c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        }
5221c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5231c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        printPreRegister.set(registerCount-parameterRegisterCount, registerCount);
5241c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    }
5251c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5261c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private void addDestRegs(BitSet printPostRegister, AnalyzedInstruction analyzedInstruction) {
5271c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        for (int registerNum=0; registerNum<registerCount; registerNum++) {
5281c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            if (analyzedInstruction.getPreInstructionRegisterType(registerNum) !=
5291c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                    analyzedInstruction.getPostInstructionRegisterType(registerNum)) {
5301c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                printPostRegister.set(registerNum);
5311c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
5321c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        }
5331c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    }
5341c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5351c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5361c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private String getPreInstructionRegisterString(AnalyzedInstruction instruction, BitSet registers) {
5377e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        StringBuilder sb = new StringBuilder();
5387e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
5391c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        for (int registerNum = registers.nextSetBit(0); registerNum >= 0;
5401c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com             registerNum = registers.nextSetBit(registerNum + 1)) {
5411c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5421c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            RegisterType registerType = instruction.getPreInstructionRegisterType(registerNum);
5431c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append(RegisterFormatter.formatRegister(encodedMethod.codeItem,registerNum));
5447e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            sb.append("=");
5457e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            if (registerType == null) {
5467e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                sb.append("null");
5477e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            } else {
5487e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com                sb.append(registerType.toString());
5497e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            }
5507e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            sb.append(";");
5517e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        }
5527e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
5537e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        return sb.toString();
5547e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com    }
5557e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
5561c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com    private String getPostInstructionRegisterString(AnalyzedInstruction instruction, BitSet registers) {
5577e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        StringBuilder sb = new StringBuilder();
5587e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
5591c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com        for (int registerNum = registers.nextSetBit(0); registerNum >= 0;
5601c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com             registerNum = registers.nextSetBit(registerNum + 1)) {
5611c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com
5621c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            RegisterType registerType = instruction.getPostInstructionRegisterType(registerNum);
5631c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            sb.append(RegisterFormatter.formatRegister(encodedMethod.codeItem,registerNum));
5647e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            sb.append("=");
5651c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            if (registerType == null) {
5661c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                sb.append("null");
5671c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            } else {
5681c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com                sb.append(registerType.toString());
5691c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com            }
5707e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com            sb.append(";");
5717e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        }
5727e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
5737e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com        return sb.toString();
5747e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com    }
5757e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com
576b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private void addTries(List<MethodItem> methodItems) {
577b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        if (encodedMethod.codeItem == null || encodedMethod.codeItem.getTries() == null) {
578b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            return;
579b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        }
580e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com
581b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        Instruction[] instructions = encodedMethod.codeItem.getInstructions();
582b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
583b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) {
584b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            int startAddress = tryItem.getStartCodeAddress();
585b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            int endAddress = tryItem.getStartCodeAddress() + tryItem.getTryLength();
586b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
587b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            /**
588b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * The end address points to the address immediately after the end of the last
589b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * instruction that the try block covers. We want the .catch directive and end_try
590b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * label to be associated with the last covered instruction, so we need to get
591b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * the address for that instruction
592b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             */
593b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
594b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            int index = instructionMap.get(endAddress, -1);
595b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            int lastInstructionAddress;
596b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
597b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            /**
598b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * If we couldn't find the index, then the try block probably extends to the last instruction in the
599b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * method, and so endAddress would be the address immediately after the end of the last instruction.
600b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             * Check to make sure this is the case, if not, throw an exception.
601b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com             */
602b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            if (index == -1) {
603b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                Instruction lastInstruction = instructions[instructions.length - 1];
604b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                lastInstructionAddress = instructionMap.keyAt(instructionMap.size() - 1);
605b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com
606b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                if (endAddress != lastInstructionAddress + lastInstruction.getSize(lastInstructionAddress)) {
607b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    throw new RuntimeException("Invalid code offset " + endAddress + " for the try block end address");
608e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com                }
6095b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com            } else {
610b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                if (index == 0) {
611b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    throw new RuntimeException("Unexpected instruction index");
612fda2e631ac0b1ca092973b7fff4b2f38d2c23437JesusFreke@JesusFreke.com                }
613b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                Instruction lastInstruction = instructions[index - 1];
6145b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com
615b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                if (lastInstruction.getFormat().variableSizeFormat) {
616b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    throw new RuntimeException("This try block unexpectedly ends on a switch/array data block.");
617fda2e631ac0b1ca092973b7fff4b2f38d2c23437JesusFreke@JesusFreke.com                }
6185b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com
619b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                //getSize for non-variable size formats should return the same size regardless of code address, so just
620b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                //use a dummy address of "0"
621b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                lastInstructionAddress = endAddress - lastInstruction.getSize(0);
6225b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.com            }
6235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
624b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            //add the catch all handler if it exists
625b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress();
626b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            if (catchAllAddress != -1) {
627b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                CatchMethodItem catchAllMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, stg, null,
628b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        startAddress, endAddress, catchAllAddress);
629b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                methodItems.add(catchAllMethodItem);
630e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            }
631ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com
632b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            //add the rest of the handlers
633b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) {
634b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                //use the address from the last covered instruction
635b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, stg,
636b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress());
637b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                methodItems.add(catchMethodItem);
638c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com            }
639c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com        }
640b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
641c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com
642b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private void addDebugInfo(final List<MethodItem> methodItems) {
643b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        if (encodedMethod.codeItem == null || encodedMethod.codeItem.getDebugInfo() == null) {
644b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            return;
645c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com        }
646c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com
647b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        final CodeItem codeItem = encodedMethod.codeItem;
648b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        DebugInfoItem debugInfoItem = codeItem.getDebugInfo();
649cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com
650b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(),
651b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() {
652b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
653b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessStartLocal(int codeAddress, int length, int registerNum, StringIdItem name,
654b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                                  TypeIdItem type) {
655b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal",
656b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                -1, registerNum, name, type, null));
657b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    }
658cf6729c1ee64e732f28eb40386ecc69d4fb6b401JesusFreke@JesusFreke.com
659b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
660b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessStartLocalExtended(int codeAddress, int length, int registerNum,
661b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                                          StringIdItem name, TypeIdItem type,
662b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                                          StringIdItem signature) {
663b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal",
664b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                -1, registerNum, name, type, signature));
6659bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com                    }
666b6547e8fd56242dde90275d9b0ba6f3639083a61JesusFreke@JesusFreke.com
667b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
668b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessEndLocal(int codeAddress, int length, int registerNum, StringIdItem name,
669b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                                TypeIdItem type, StringIdItem signature) {
670b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "EndLocal", -1,
671b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                registerNum, name, type, signature));
672d7df5938b154b6d83c8c2e1c7a6fe47f41797e0dJesusFreke@JesusFreke.com                    }
673b6547e8fd56242dde90275d9b0ba6f3639083a61JesusFreke@JesusFreke.com
674b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
675b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessRestartLocal(int codeAddress, int length, int registerNum, StringIdItem name,
676b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                                    TypeIdItem type, StringIdItem signature) {
677b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "RestartLocal", -1,
678b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                registerNum, name, type, signature));
679b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    }
680b6547e8fd56242dde90275d9b0ba6f3639083a61JesusFreke@JesusFreke.com
681b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
682b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessSetPrologueEnd(int codeAddress) {
683b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new DebugMethodItem(codeAddress, stg, "EndPrologue", -4));
684b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    }
685b6547e8fd56242dde90275d9b0ba6f3639083a61JesusFreke@JesusFreke.com
686b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
687b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessSetEpilogueBegin(int codeAddress) {
688b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new DebugMethodItem(codeAddress, stg, "StartEpilogue", -4));
689b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    }
690b6547e8fd56242dde90275d9b0ba6f3639083a61JesusFreke@JesusFreke.com
691b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
692b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) {
693b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        methodItems.add(new DebugMethodItem(codeAddress, stg, "SetFile", -3) {
694b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                            @Override
695b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                            protected void setAttributes(StringTemplate template) {
696b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                template.setAttribute("FileName", name.getStringValue());
697b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                            }
698b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                        });
699b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    }
7003c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com
701b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    @Override
702b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    public void ProcessLineEmit(int codeAddress, final int line) {
703b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                         methodItems.add(new DebugMethodItem(codeAddress, stg, "Line", -2) {
704b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                             @Override
705b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                             protected void setAttributes(StringTemplate template) {
706b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                                 template.setAttribute("Line", line);
707b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                             }
708b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                         });
709b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                    }
710b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                });
711b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    }
712e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
713b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com    private void setLabelSequentialNumbers() {
714b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>();
715b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels());
716e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
717b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        //sort the labels by their location in the method
718b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        Collections.sort(sortedLabels);
719e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
720b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com        for (LabelMethodItem labelMethodItem: sortedLabels) {
721b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix());
722b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            if (labelSequence == null) {
723b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com                labelSequence = 0;
724e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            }
725b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            labelMethodItem.setLabelSequence(labelSequence);
726b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com            nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1);
727e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        }
728e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com    }
729e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
730e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com    public static class LabelCache {
731e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>();
732e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
733e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        public LabelCache() {
734e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        }
735e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
736e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) {
737e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem);
738e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            if (internedLabelMethodItem != null) {
739e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com                if (!labelMethodItem.isCommentedOut()) {
740e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com                    internedLabelMethodItem.setUncommented();
741e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com                }
742e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com                return internedLabelMethodItem;
743e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            }
744e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            labels.put(labelMethodItem, labelMethodItem);
745e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            return labelMethodItem;
746e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        }
747e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
748e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com
749e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        public Collection<LabelMethodItem> getLabels() {
750e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com            return labels.values();
751e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com        }
75236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com    }
75336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com}
754