1 /* 2 * Copyright 2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 package org.jf.dexlib2.builder; 33 34 import org.jf.dexlib2.iface.MethodImplementation; 35 import org.jf.dexlib2.iface.reference.StringReference; 36 import org.jf.dexlib2.iface.reference.TypeReference; 37 38 import javax.annotation.Nonnull; 39 import javax.annotation.Nullable; 40 import java.util.HashMap; 41 42 public class MethodImplementationBuilder { 43 // Contains all named labels - both placed and unplaced 44 private final HashMap<String, Label> labels = new HashMap<String, Label>(); 45 46 @Nonnull 47 private final MutableMethodImplementation impl; 48 49 private MethodLocation currentLocation; 50 MethodImplementationBuilder(int registerCount)51 public MethodImplementationBuilder(int registerCount) { 52 this.impl = new MutableMethodImplementation(registerCount); 53 this.currentLocation = impl.instructionList.get(0); 54 } 55 getMethodImplementation()56 public MethodImplementation getMethodImplementation() { 57 return impl; 58 } 59 60 /** 61 * Adds a new named label at the current location. 62 * 63 * Any previous unplaced references to a label of this name will now refer to this label/location 64 * 65 * @param name The name of the label to add 66 * @return A LabelRef representing the label 67 */ 68 @Nonnull addLabel(@onnull String name)69 public Label addLabel(@Nonnull String name) { 70 Label label = labels.get(name); 71 72 if (label != null) { 73 if (label.isPlaced()) { 74 throw new IllegalArgumentException("There is already a label with that name."); 75 } else { 76 currentLocation.getLabels().add(label); 77 } 78 } else { 79 label = currentLocation.addNewLabel(); 80 labels.put(name, label); 81 } 82 83 return label; 84 } 85 86 /** 87 * Get a reference to a label with the given name. 88 * 89 * If a label with that name has not been added yet, a new one is created, but is left 90 * in an unplaced state. It is assumed that addLabel(name) will be called at a later 91 * point to define the location of the label. 92 * 93 * @param name The name of the label to get 94 * @return A LabelRef representing the label 95 */ 96 @Nonnull getLabel(@onnull String name)97 public Label getLabel(@Nonnull String name) { 98 Label label = labels.get(name); 99 if (label == null) { 100 label = new Label(); 101 labels.put(name, label); 102 } 103 return label; 104 } 105 addCatch(@ullable TypeReference type, @Nonnull Label from, @Nonnull Label to, @Nonnull Label handler)106 public void addCatch(@Nullable TypeReference type, @Nonnull Label from, 107 @Nonnull Label to, @Nonnull Label handler) { 108 impl.addCatch(type, from, to, handler); 109 } 110 addCatch(@ullable String type, @Nonnull Label from, @Nonnull Label to, @Nonnull Label handler)111 public void addCatch(@Nullable String type, @Nonnull Label from, @Nonnull Label to, 112 @Nonnull Label handler) { 113 impl.addCatch(type, from, to, handler); 114 } 115 addCatch(@onnull Label from, @Nonnull Label to, @Nonnull Label handler)116 public void addCatch(@Nonnull Label from, @Nonnull Label to, @Nonnull Label handler) { 117 impl.addCatch(from, to, handler); 118 } 119 addLineNumber(int lineNumber)120 public void addLineNumber(int lineNumber) { 121 currentLocation.addLineNumber(lineNumber); 122 } 123 addStartLocal(int registerNumber, @Nullable StringReference name, @Nullable TypeReference type, @Nullable StringReference signature)124 public void addStartLocal(int registerNumber, @Nullable StringReference name, @Nullable TypeReference type, 125 @Nullable StringReference signature) { 126 currentLocation.addStartLocal(registerNumber, name, type, signature); 127 } 128 addEndLocal(int registerNumber)129 public void addEndLocal(int registerNumber) { 130 currentLocation.addEndLocal(registerNumber); 131 } 132 addRestartLocal(int registerNumber)133 public void addRestartLocal(int registerNumber) { 134 currentLocation.addRestartLocal(registerNumber); 135 } 136 addPrologue()137 public void addPrologue() { 138 currentLocation.addPrologue(); 139 } 140 addEpilogue()141 public void addEpilogue() { 142 currentLocation.addEpilogue(); 143 } 144 addSetSourceFile(@ullable StringReference sourceFile)145 public void addSetSourceFile(@Nullable StringReference sourceFile) { 146 currentLocation.addSetSourceFile(sourceFile); 147 } 148 addInstruction(@ullable BuilderInstruction instruction)149 public void addInstruction(@Nullable BuilderInstruction instruction) { 150 impl.addInstruction(instruction); 151 currentLocation = impl.instructionList.get(impl.instructionList.size()-1); 152 } 153 } 154