• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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