15ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver/* 25ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * Copyright 2013, Google Inc. 35ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * All rights reserved. 45ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * 55ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * Redistribution and use in source and binary forms, with or without 65ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * modification, are permitted provided that the following conditions are 75ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * met: 85ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * 95ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * * Redistributions of source code must retain the above copyright 105ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * notice, this list of conditions and the following disclaimer. 115ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * * Redistributions in binary form must reproduce the above 125ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * copyright notice, this list of conditions and the following disclaimer 135ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * in the documentation and/or other materials provided with the 145ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * distribution. 155ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * * Neither the name of Google Inc. nor the names of its 165ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * contributors may be used to endorse or promote products derived from 175ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * this software without specific prior written permission. 185ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * 195ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 205ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 215ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 225ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 235ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 245ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 255ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 265ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 275ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 285ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 295ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 305ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver */ 315ff4ee9a3fc898dbe9a67386e984f14c21338391Ben Gruver 32766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruverpackage org.jf.dexlib2.builder; 33766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 34e80efa670f1027fdf3882a298216a460199e38d0Ben Gruverimport org.jf.dexlib2.iface.MethodImplementation; 35766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruverimport org.jf.dexlib2.iface.reference.StringReference; 36766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruverimport org.jf.dexlib2.iface.reference.TypeReference; 37766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 38766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruverimport javax.annotation.Nonnull; 39766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruverimport javax.annotation.Nullable; 40160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruverimport java.util.HashMap; 41766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 42e80efa670f1027fdf3882a298216a460199e38d0Ben Gruverpublic class MethodImplementationBuilder { 43160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver // Contains all named labels - both placed and unplaced 44bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver private final HashMap<String, Label> labels = new HashMap<String, Label>(); 45160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver 46160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver @Nonnull 47e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver private final MutableMethodImplementation impl; 48160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver 49897832aa150cdf53ed7fa2f17dee132d2408e2f3Ben Gruver private MethodLocation currentLocation; 50766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 51160449b83a0a19244ae27d0c9acf539c0c730be5Ben Gruver public MethodImplementationBuilder(int registerCount) { 52160449b83a0a19244ae27d0c9acf539c0c730be5Ben Gruver this.impl = new MutableMethodImplementation(registerCount); 53897832aa150cdf53ed7fa2f17dee132d2408e2f3Ben Gruver this.currentLocation = impl.instructionList.get(0); 54766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 55766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 56160449b83a0a19244ae27d0c9acf539c0c730be5Ben Gruver public MethodImplementation getMethodImplementation() { 57160449b83a0a19244ae27d0c9acf539c0c730be5Ben Gruver return impl; 58e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver } 59e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver 60160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver /** 61160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * Adds a new named label at the current location. 62160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * 63160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * Any previous unplaced references to a label of this name will now refer to this label/location 64160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * 65160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * @param name The name of the label to add 66160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * @return A LabelRef representing the label 67160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver */ 68766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver @Nonnull 69bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver public Label addLabel(@Nonnull String name) { 70bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver Label label = labels.get(name); 71160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver 72160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver if (label != null) { 73160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver if (label.isPlaced()) { 74160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver throw new IllegalArgumentException("There is already a label with that name."); 75160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } else { 76688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.getLabels().add(label); 77160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } 78160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } else { 79897832aa150cdf53ed7fa2f17dee132d2408e2f3Ben Gruver label = currentLocation.addNewLabel(); 80160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver labels.put(name, label); 81160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } 82160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver 83160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver return label; 84160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } 85160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver 86160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver /** 87160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * Get a reference to a label with the given name. 88160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * 89160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * If a label with that name has not been added yet, a new one is created, but is left 90160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * in an unplaced state. It is assumed that addLabel(name) will be called at a later 91160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * point to define the location of the label. 92160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * 93160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * @param name The name of the label to get 94160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver * @return A LabelRef representing the label 95160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver */ 96160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver @Nonnull 97bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver public Label getLabel(@Nonnull String name) { 98bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver Label label = labels.get(name); 99160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver if (label == null) { 100bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver label = new Label(); 101160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver labels.put(name, label); 102160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } 103160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver return label; 104766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 105766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 106bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver public void addCatch(@Nullable TypeReference type, @Nonnull Label from, 107bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver @Nonnull Label to, @Nonnull Label handler) { 108897832aa150cdf53ed7fa2f17dee132d2408e2f3Ben Gruver impl.addCatch(type, from, to, handler); 109160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver } 110160fc1cdbabb1aafaadde1f8d872574b0666f1dcBen Gruver 111bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver public void addCatch(@Nullable String type, @Nonnull Label from, @Nonnull Label to, 112bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver @Nonnull Label handler) { 113897832aa150cdf53ed7fa2f17dee132d2408e2f3Ben Gruver impl.addCatch(type, from, to, handler); 114766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 115766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 116bb7937fd308738b46db61e5e6181dff3c8e6e19eBen Gruver public void addCatch(@Nonnull Label from, @Nonnull Label to, @Nonnull Label handler) { 117897832aa150cdf53ed7fa2f17dee132d2408e2f3Ben Gruver impl.addCatch(from, to, handler); 118766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 119766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 120766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver public void addLineNumber(int lineNumber) { 121688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addLineNumber(lineNumber); 122766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 123766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 124766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver public void addStartLocal(int registerNumber, @Nullable StringReference name, @Nullable TypeReference type, 125766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver @Nullable StringReference signature) { 126688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addStartLocal(registerNumber, name, type, signature); 127766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 128766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 129766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver public void addEndLocal(int registerNumber) { 130688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addEndLocal(registerNumber); 131766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 132766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 133766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver public void addRestartLocal(int registerNumber) { 134688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addRestartLocal(registerNumber); 135766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 136766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 137766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver public void addPrologue() { 138688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addPrologue(); 139766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 140766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 141766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver public void addEpilogue() { 142688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addEpilogue(); 143766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 144766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 145263083faede803c028b2807b4abe761391bc3a98Ben Gruver public void addSetSourceFile(@Nullable StringReference sourceFile) { 146688611814ddff6babff935e81dcf51aff903563aBen Gruver currentLocation.addSetSourceFile(sourceFile); 147766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 148766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver 149e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver public void addInstruction(@Nullable BuilderInstruction instruction) { 150e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver impl.addInstruction(instruction); 151e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver currentLocation = impl.instructionList.get(impl.instructionList.size()-1); 152766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver } 153766f285a70af96d09c3cd1d47fce5f9c76bbb616Ben Gruver} 154