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