1 cananian 1.1.2.24 // Code.java, created Mon Feb 8 16:55:15 1999 by duncan 2 cananian 1.1.2.23 // Copyright (C) 1998 Duncan Bryce <duncan@lcs.mit.edu> 3 cananian 1.1.2.23 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 duncan 1.1.2.1 package harpoon.IR.Tree; 5 duncan 1.1.2.1 6 cananian 1.1.2.41 import harpoon.Analysis.Maps.Derivation; 7 cananian 1.1.2.41 import harpoon.Analysis.Maps.Derivation.DList; 8 duncan 1.1.2.2 import harpoon.Analysis.Maps.TypeMap; 9 duncan 1.1.2.1 import harpoon.Backend.Generic.Frame; 10 duncan 1.1.2.2 import harpoon.ClassFile.HClass; 11 duncan 1.1.2.1 import harpoon.ClassFile.HCode; 12 cananian 1.1.2.51 import harpoon.ClassFile.HCodeAndMaps; 13 duncan 1.1.2.1 import harpoon.ClassFile.HCodeElement; 14 duncan 1.1.2.1 import harpoon.ClassFile.HMethod; 15 duncan 1.1.2.38 import harpoon.IR.Properties.CFGrapher; 16 cananian 1.1.2.46 import harpoon.IR.Properties.UseDefer; 17 duncan 1.1.2.1 import harpoon.Util.ArrayFactory; 18 duncan 1.1.2.12 import harpoon.Util.Util; 19 duncan 1.1.2.12 import harpoon.Temp.LabelList; 20 duncan 1.1.2.1 import harpoon.Temp.Temp; 21 duncan 1.1.2.1 import harpoon.Temp.TempFactory; 22 cananian 1.1.2.51 import harpoon.Temp.TempMap; 23 cananian 1.9 import net.cscott.jutil.UnmodifiableIterator; 24 duncan 1.1.2.1 25 duncan 1.1.2.19 import java.util.ArrayList; 26 cananian 1.1.2.51 import java.util.Collections; 27 cananian 1.6 import java.util.ConcurrentModificationException; 28 duncan 1.1.2.19 import java.util.HashMap; 29 duncan 1.1.2.19 import java.util.HashSet; 30 duncan 1.1.2.19 import java.util.Iterator; 31 duncan 1.1.2.19 import java.util.List; 32 duncan 1.1.2.19 import java.util.Map; 33 duncan 1.1.2.1 import java.util.NoSuchElementException; 34 duncan 1.1.2.19 import java.util.Set; 35 duncan 1.1.2.1 import java.util.Stack; 36 duncan 1.1.2.1 37 duncan 1.1.2.19 /** 38 duncan 1.1.2.19 * <code>Tree.Code</code> is an abstract superclass of codeviews 39 duncan 1.1.2.19 * using the components in <code>IR.Tree</code>. It implements 40 duncan 1.1.2.19 * shared methods for the various codeviews using <code>Tree</code>s. 41 duncan 1.1.2.19 * 42 duncan 1.1.2.19 * @author Duncan Bryce <duncan@lcs.mit.edu> 43 cananian 1.9 * @version $Id: Code.java,v 1.9 2004/02/08 01:55:51 cananian Exp $ 44 duncan 1.1.2.19 */ 45 cananian 1.3.2.2 public abstract class Code extends HCode<Tree> { 46 duncan 1.1.2.11 /** The Tree Objects composing this code view. */ 47 duncan 1.1.2.11 protected Tree tree; 48 pnkfelix 1.1.2.17 49 pnkfelix 1.1.2.17 /** The Frame containing machine-specific information*/ 50 andyb 1.1.2.16 protected /* final */ Frame frame; 51 pnkfelix 1.1.2.17 52 duncan 1.1.2.11 /** Tree factory. */ 53 andyb 1.1.2.16 protected /* final */ TreeFactory tf; 54 pnkfelix 1.1.2.17 55 duncan 1.1.2.11 /** The method that this code view represents. */ 56 andyb 1.1.2.16 protected /* final */ HMethod parent; 57 duncan 1.1.2.1 58 cananian 1.6 /** Keep track of modifications to this <code>Code</code> so that the 59 cananian 1.6 * <code>getElementsI()</code> <code>Iterator</code> can fail-fast. */ 60 cananian 1.6 private int modCount=0; 61 cananian 1.6 62 duncan 1.1.2.15 /** Create a proper TreeFactory. */ 63 cananian 1.1.2.30 public class TreeFactory extends harpoon.IR.Tree.TreeFactory { 64 cananian 1.1.2.30 private int id=0; 65 cananian 1.1.2.31 private final TempFactory tempf; 66 cananian 1.1.2.31 TreeFactory(String scope) { this.tempf = Temp.tempFactory(scope); } 67 cananian 1.1.2.31 public TempFactory tempFactory() { return tempf; } 68 cananian 1.1.2.30 /** Returns the <code>HCode</code> to which all <code>Exp</code>s and 69 cananian 1.1.2.30 * <code>Stm</code>s generated by this factory belong. */ 70 cananian 1.1.2.30 public Code getParent() { return Code.this; } 71 cananian 1.6 /** Indicate that the parent has changed, so that its 72 cananian 1.6 * fail-fast iterators will work correctly. */ 73 cananian 1.6 void incModCount() { Code.this.modCount++; } 74 cananian 1.1.2.30 /** Returns the <code>HMethod</code> to which all <code>Exp</code>s and 75 cananian 1.1.2.30 * <code>Stm</code>s generated by this factory belong. */ 76 cananian 1.1.2.30 public HMethod getMethod() { return Code.this.getMethod(); } 77 cananian 1.1.2.30 public Frame getFrame() { return Code.this.frame; } 78 cananian 1.1.2.30 synchronized int getUniqueID() { return id++; } 79 cananian 1.1.2.30 public String toString() { 80 cananian 1.1.2.30 return "Code.TreeFactory["+getParent().toString()+"]"; 81 cananian 1.1.2.30 } 82 cananian 1.1.2.30 public int hashCode() { return Code.this.hashCode(); } 83 duncan 1.1.2.1 } 84 duncan 1.1.2.1 85 duncan 1.1.2.11 /** constructor. */ 86 duncan 1.1.2.11 protected Code(final HMethod parent, final Tree tree, 87 cananian 1.1.2.31 final Frame frame) { 88 duncan 1.1.2.11 final String scope = parent.getDeclaringClass().getName() + "." + 89 duncan 1.1.2.11 parent.getName() + parent.getDescriptor() + "/" + getName(); 90 pnkfelix 1.1.2.49 91 duncan 1.1.2.11 this.parent = parent; 92 duncan 1.1.2.11 this.tree = tree; 93 cananian 1.1.2.31 this.frame = frame; 94 cananian 1.1.2.31 this.tf = new TreeFactory(scope); 95 duncan 1.1.2.1 } 96 duncan 1.1.2.1 97 duncan 1.1.2.11 /** Clone this code representation. The clone has its own copy 98 duncan 1.1.2.19 * of the Tree */ 99 cananian 1.7 public abstract HCodeAndMaps<Tree> clone(HMethod newMethod, Frame frame); 100 cananian 1.1.2.51 /** Helps to create a proper <code>HCodeAndMaps</code> during cloning */ 101 cananian 1.7 protected final HCodeAndMaps<Tree> cloneHelper(final Code tc, 102 cananian 1.1.2.51 final DerivationGenerator dg) { 103 cananian 1.1.2.51 final Tree.CloneCallback ccb = 104 cananian 1.1.2.51 (dg==null) ? null : dg.cloneCallback(getTreeDerivation()); 105 cananian 1.7 final Map<Tree,Tree> 106 cananian 1.7 o2nTree = new HashMap<Tree,Tree>(), 107 cananian 1.7 n2oTree = new HashMap<Tree,Tree>(); 108 cananian 1.7 final Map<Temp,Temp> 109 cananian 1.7 o2nTemp = new HashMap<Temp,Temp>(), 110 cananian 1.7 n2oTemp = new HashMap<Temp,Temp>(); 111 cananian 1.1.2.51 tc.tree = Tree.clone(tc.tf, tree, new Tree.CloneCallback() { 112 cananian 1.1.2.51 public Tree callback(Tree o, Tree n, TempMap tm) { 113 cananian 1.1.2.51 if (ccb!=null) n = ccb.callback(o, n, tm); 114 cananian 1.1.2.51 o2nTree.put(o, n); n2oTree.put(n, o); 115 cananian 1.1.2.51 if (n instanceof TEMP) { 116 cananian 1.1.2.51 Temp oT = ((TEMP)o).temp, nT = ((TEMP)n).temp; 117 cananian 1.1.2.51 o2nTemp.put(oT, nT); n2oTemp.put(nT, oT); 118 cananian 1.1.2.51 } 119 cananian 1.1.2.51 return n; 120 cananian 1.1.2.51 } 121 cananian 1.1.2.51 }); 122 cananian 1.1.2.52 class MapTempMap implements TempMap { 123 cananian 1.7 private final Map<Temp,Temp> m; 124 cananian 1.7 MapTempMap(Map<Temp,Temp> m) { this.m = m; } 125 cananian 1.7 public Temp tempMap(Temp t) { return m.get(t); } 126 cananian 1.1.2.52 } 127 cananian 1.7 return new HCodeAndMaps<Tree>(tc, 128 cananian 1.1.2.52 Collections.unmodifiableMap(o2nTree), 129 cananian 1.1.2.52 new MapTempMap(o2nTemp), 130 cananian 1.1.2.52 this, 131 cananian 1.1.2.52 Collections.unmodifiableMap(n2oTree), 132 cananian 1.1.2.52 new MapTempMap(n2oTemp)); 133 cananian 1.1.2.51 } 134 cananian 1.1.2.45 /** Clone this code representation. The clone has its own copy 135 cananian 1.1.2.45 * of the Tree */ 136 cananian 1.7 public final HCodeAndMaps<Tree> clone(HMethod newMethod) { 137 cananian 1.1.2.45 return clone(newMethod, frame); 138 cananian 1.1.2.45 } 139 duncan 1.1.2.38 140 duncan 1.1.2.38 /** Returns a means to externally associate control flow with this 141 duncan 1.1.2.38 * tree code. If this tree code is modified subsequent to a call 142 duncan 1.1.2.38 * to <code>getGrapher()</code>, the grapher is invalid, this method 143 duncan 1.1.2.38 * should be re-invoked to acquire a new grapher. 144 duncan 1.1.2.38 */ 145 cananian 1.3.2.3 public CFGrapher<Tree> getGrapher() { return new TreeGrapher(this); } 146 cananian 1.1.2.46 /** Returns a means to externally associate use/def information with 147 cananian 1.1.2.46 * this tree code. MOVE(TEMP(t), ...) and CALL/NATIVECALLs are treated 148 cananian 1.1.2.46 * as defs; all instances of TEMP in any of the subtrees returned 149 cananian 1.1.2.46 * by the <code>kids()</code> method are considered uses. Not 150 cananian 1.1.2.46 * valid for non-canonical forms. */ 151 cananian 1.3.2.3 public UseDefer<Tree> getUseDefer() { return new TreeUseDefer(this); } 152 duncan 1.1.2.38 153 duncan 1.1.2.11 /** Return the name of this code view. */ 154 duncan 1.1.2.11 public abstract String getName(); 155 duncan 1.1.2.19 156 duncan 1.1.2.11 /** Return the <code>HMethod</code> this codeview 157 duncan 1.1.2.19 * belongs to. */ 158 duncan 1.1.2.11 public HMethod getMethod() { return this.parent; } 159 duncan 1.1.2.1 160 duncan 1.1.2.11 public Frame getFrame() { return this.frame; } 161 andyb 1.1.2.9 162 cananian 1.1.2.42 public abstract TreeDerivation getTreeDerivation(); 163 cananian 1.1.2.42 164 duncan 1.1.2.11 /** Returns the root of the Tree */ 165 cananian 1.3.2.2 public Tree getRootElement() { 166 duncan 1.1.2.21 // Ensures that the root is a SEQ, and the first instruction is 167 duncan 1.1.2.21 // a SEGMENT. 168 duncan 1.1.2.27 Tree first = (SEQ)this.tree; 169 duncan 1.1.2.39 while(first.kind()==TreeKind.SEQ) first = ((SEQ)first).getLeft(); 170 cananian 1.3.2.1 assert first.kind()==TreeKind.SEGMENT; 171 duncan 1.1.2.21 return this.tree; 172 duncan 1.1.2.21 } 173 duncan 1.1.2.1 174 duncan 1.1.2.11 /** Returns the leaves of the Tree */ 175 cananian 1.3.2.2 public Tree[] getLeafElements() { 176 cananian 1.1.2.44 // what exactly does 'leaf elements' *mean* in this context? 177 cananian 1.1.2.44 return new Tree[0]; 178 duncan 1.1.2.1 } 179 duncan 1.1.2.1 180 duncan 1.1.2.11 /** 181 duncan 1.1.2.19 * Returns an ordered list of the <code>Tree</code> Objects 182 duncan 1.1.2.19 * making up this code view. The root of the tree 183 duncan 1.1.2.19 * is in element 0 of the array. 184 cananian 1.8 * @deprecated 185 duncan 1.1.2.19 */ 186 cananian 1.3.2.2 public Tree[] getElements() { 187 duncan 1.1.2.19 return super.getElements(); 188 duncan 1.1.2.1 } 189 duncan 1.1.2.1 190 duncan 1.1.2.19 /** 191 duncan 1.1.2.19 * Returns an <code>Iterator</code> of the <code>Tree</code> Objects 192 duncan 1.1.2.19 * making up this code view. The root of the tree is the first element 193 cananian 1.1.2.48 * of the Iterator. Returns the elements of the tree in depth-first 194 cananian 1.1.2.48 * pre-order. 195 duncan 1.1.2.19 */ 196 cananian 1.3.2.2 public Iterator<Tree> getElementsI() { 197 cananian 1.3.2.2 return new UnmodifiableIterator<Tree>() { 198 cananian 1.6 // record # of modifications to enable fail-fast. 199 cananian 1.6 int modCount = Code.this.modCount; 200 cananian 1.6 // set up worklists. 201 cananian 1.3.2.2 Stack<Tree> stack = new Stack<Tree>(), aux = new Stack<Tree>(); 202 cananian 1.1.2.44 { // initialize stack/set 203 cananian 1.1.2.48 stack.push(getRootElement()); 204 duncan 1.1.2.11 } 205 cananian 1.1.2.44 public boolean hasNext() { return !stack.isEmpty(); } 206 cananian 1.3.2.2 public Tree next() { 207 cananian 1.6 if (modCount != Code.this.modCount) 208 cananian 1.6 throw new ConcurrentModificationException(); 209 duncan 1.1.2.11 if (stack.isEmpty()) throw new NoSuchElementException(); 210 cananian 1.3.2.2 Tree t = stack.pop(); 211 cananian 1.1.2.44 // Push successors on stack before returning 212 cananian 1.1.2.44 // (reverse the order twice to get things right) 213 cananian 1.1.2.44 for (Tree tp = t.getFirstChild(); tp!=null; tp=tp.getSibling()) 214 cananian 1.1.2.48 aux.push(tp); 215 cananian 1.1.2.44 while (!aux.isEmpty()) 216 cananian 1.1.2.44 stack.push(aux.pop()); //LIFO twice. 217 duncan 1.1.2.11 return t; 218 duncan 1.1.2.1 } 219 duncan 1.1.2.11 }; 220 duncan 1.1.2.1 } 221 duncan 1.1.2.1 222 duncan 1.1.2.11 // implement elementArrayFactory which returns Tree[]s. 223 cananian 1.3.2.2 public ArrayFactory<Tree> elementArrayFactory() { 224 cananian 1.3.2.2 return Tree.arrayFactory; 225 cananian 1.3.2.2 } 226 andyb 1.1.2.6 227 cananian 1.3.2.2 public void print(java.io.PrintWriter pw, PrintCallback<Tree> callback) { 228 cananian 1.1.2.53 Print.print(pw, this, callback); 229 duncan 1.1.2.11 } 230 andyb 1.1.2.7 231 duncan 1.1.2.19 /** 232 duncan 1.1.2.19 * Returns true if this codeview is a canonical representation 233 duncan 1.1.2.19 */ 234 duncan 1.1.2.19 public abstract boolean isCanonical(); 235 duncan 1.1.2.12 236 duncan 1.1.2.40 /** 237 duncan 1.1.2.40 * Removes the specified <code>Stm</code> from the tree in which it 238 duncan 1.1.2.40 * resides. 239 duncan 1.1.2.40 * 240 duncan 1.1.2.40 * <br><b>Requires:</b> 241 duncan 1.1.2.40 * <ol> 242 duncan 1.1.2.40 * <li><code>stm</code> is not of type <code>SEQ</code>. 243 duncan 1.1.2.40 * <li><code>stm.getParent()</code> must be of type <code>SEQ</code>. 244 duncan 1.1.2.40 * <li><code>stm</code> is an element of this codeview. 245 duncan 1.1.2.40 * <li><code>stm</code> is not the root element of this codeview. 246 duncan 1.1.2.40 * </ol> 247 duncan 1.1.2.40 * <br><b>Effects:</b> 248 duncan 1.1.2.40 * Removes <code>stm</code> from this tree. 249 duncan 1.1.2.40 */ 250 duncan 1.1.2.40 public void remove(Stm stm) { 251 cananian 1.3.2.1 assert stm.kind() != TreeKind.SEQ; 252 cananian 1.3.2.1 assert stm.getFactory() == this.tf; 253 cananian 1.3.2.1 assert this.tf.getParent() == this; 254 duncan 1.1.2.40 255 duncan 1.1.2.40 // All predecessors in canonical tree form must be SEQs 256 duncan 1.1.2.40 SEQ pred = (SEQ)stm.getParent(); 257 duncan 1.1.2.40 Stm newPred; 258 duncan 1.1.2.40 259 duncan 1.1.2.40 if (pred.getLeft()==stm) { newPred = pred.getRight(); } 260 duncan 1.1.2.40 else if (pred.getRight()==stm) { newPred = pred.getLeft(); } 261 duncan 1.1.2.40 else { throw new Error("Invalid tree form!"); } 262 duncan 1.1.2.40 263 duncan 1.1.2.40 if (pred.getParent() == null) { 264 duncan 1.1.2.40 // Pred has no parents, it must be the root of the tree. 265 cananian 1.3.2.1 assert pred == this.tree; 266 duncan 1.1.2.40 this.tree = newPred; 267 cananian 1.1.2.43 this.tree.unlink(); 268 duncan 1.1.2.40 } 269 duncan 1.1.2.40 else { 270 cananian 1.1.2.44 pred.replace(newPred); 271 duncan 1.1.2.40 } 272 duncan 1.1.2.40 } 273 duncan 1.1.2.1 } 274 duncan 1.1.2.40 275 cananian 1.2