1 cananian 1.1.2.1 // Derivation.java, created Fri Jan 22 16:46:17 1999 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.Maps; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement; 7 cananian 1.1.2.1 import harpoon.Temp.CloningTempMap; 8 cananian 1.1.2.1 import harpoon.Temp.Temp; 9 cananian 1.1.2.1 import harpoon.Temp.TempMap; 10 cananian 1.1.2.4 import harpoon.Util.Util; 11 cananian 1.1.2.1 12 cananian 1.1.2.4 import java.util.ArrayList; 13 cananian 1.1.2.4 import java.util.Collections; 14 cananian 1.1.2.4 import java.util.Comparator; 15 cananian 1.1.2.4 import java.util.Iterator; 16 cananian 1.1.2.4 import java.util.List; 17 cananian 1.1.2.1 /** 18 cananian 1.1.2.1 * <code>Derivation</code> provides a means to access the derivation 19 cananian 1.1.2.1 * of a particular derived pointer. Given a compiler temporary, it 20 cananian 1.1.2.1 * will enumerate the base pointers and signs needed to allow proper 21 cananian 1.1.2.1 * garbage collection of the derived pointer.<p> 22 cananian 1.1.2.1 * See Diwan, Moss, and Hudson, <A 23 cananian 1.1.2.1 * HREF="http://www.acm.org/pubs/citations/proceedings/pldi/143095/p273-diwan/" 24 cananian 1.1.2.1 * >"Compiler Support for Garbage Collection in a Statically Typed 25 cananian 1.1.2.1 * Language"</A> in PLDI'92 for background on the derivation structure 26 cananian 1.1.2.1 * and its motivations. 27 cananian 1.1.2.1 * 28 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 29 cananian 1.5 * @version $Id: Derivation.java,v 1.5 2002/09/02 19:23:26 cananian Exp $ 30 cananian 1.1.2.1 */ 31 cananian 1.5 public interface Derivation<HCE extends HCodeElement> 32 cananian 1.5 extends harpoon.Analysis.Maps.TypeMap<HCE> { 33 cananian 1.1.2.1 34 cananian 1.1.2.1 /** Map compiler temporaries to their derivations. 35 cananian 1.1.2.1 * @param t The temporary to query. 36 cananian 1.1.2.1 * @param hce A definition point for <code>t</code>. 37 cananian 1.1.2.1 * @return <code>null</code> if the temporary has no derivation (is 38 cananian 1.1.2.1 * a base pointer, for example), or the derivation otherwise. 39 cananian 1.1.2.1 * @exception NullPointerException if <code>t</code> or <code>hc</code> 40 cananian 1.1.2.1 * is <code>null</code>. 41 cananian 1.1.2.1 * @exception TypeNotKnownException if the <code>Derivation</code> 42 cananian 1.1.2.1 * has no information about <code>t</code> as defined 43 cananian 1.1.2.1 * at <code>hce</code>. 44 cananian 1.1.2.1 */ 45 cananian 1.5 public DList derivation(HCE hce, Temp t) 46 cananian 1.1.2.9 throws TypeMap.TypeNotKnownException; 47 cananian 1.1.2.1 48 cananian 1.1.2.2 /** Structure of the derivation information.<p> 49 cananian 1.1.2.2 * Given three <code>Temp</code>s <code>t1</code>, <code>t2</code>, 50 cananian 1.1.2.2 * and <code>t3</code>, a derived pointer <code>d</code> whose value 51 cananian 1.1.2.2 * can be described by the equation:<pre> 52 cananian 1.1.2.2 * d = K + t1 - t2 + t3 53 cananian 1.1.2.3 * </pre> for some (non-constant) integer K at every point during 54 cananian 1.1.2.3 * runtime can be represented as the <code>DList</code><pre> 55 cananian 1.1.2.2 * new DList(t1, true, new DList(t2, false, new DList(t3, true))) 56 cananian 1.1.2.2 * </pre>.<p> 57 cananian 1.1.2.2 * <b>NOTE</b> that the temporaries named in the <code>DList</code> 58 cananian 1.1.2.2 * refer to the <i>reaching definitions</i> of those temporaries at 59 cananian 1.1.2.2 * the <i>definition point</i> of the variable with the derived 60 cananian 1.1.2.2 * type. In SSI/SSA forms, this does not matter, as every variable 61 cananian 1.1.2.2 * has exactly one reaching definition, but in other forms <b>it 62 cananian 1.1.2.2 * is the responsibility of the implementor</b> to ensure that the 63 cananian 1.1.2.2 * base pointers are not overwritten while the derived value is 64 cananian 1.1.2.2 * live. 65 cananian 1.1.2.7 * <p><b>ALSO NOTE</b> that the temporaries named in the 66 cananian 1.1.2.7 * <code>DList</code> are <i>base pointers</i> -- that is, 67 cananian 1.1.2.7 * they have pure types, <i>not derived types</i>. In particular, 68 cananian 1.1.2.7 * the <code>derivation()</code> method applied to any temporary 69 cananian 1.1.2.7 * named in a <code>DList</code> should return <code>null</code>. 70 cananian 1.1.2.7 * Derived types derived from other derived types are not allowed. 71 cananian 1.1.2.2 */ 72 cananian 1.1.2.1 public static class DList { 73 cananian 1.1.2.1 /** Base pointer. */ 74 cananian 1.1.2.1 public final Temp base; 75 cananian 1.1.2.1 /** Sign of base pointer. <code>true</code> if derived pointer 76 cananian 1.1.2.1 * equals offset <b>+</b> base pointer, <code>false</code> if 77 cananian 1.1.2.1 * derived pointer equals offset <b>-</b> base pointer. */ 78 cananian 1.1.2.1 public final boolean sign; 79 cananian 1.1.2.1 /** Pointer to a continuation of the derivation, or <Code>null</code> 80 cananian 1.1.2.1 * if there are no more base pointers associated with this derived 81 cananian 1.1.2.1 * pointer. */ 82 cananian 1.1.2.1 public final DList next; 83 cananian 1.1.2.4 /** Specifies whether this <code>DList</code> is in canonical form. 84 cananian 1.1.2.4 */ 85 cananian 1.1.2.4 private final boolean canonical; 86 cananian 1.1.2.1 /** Constructor. */ 87 cananian 1.1.2.1 public DList(Temp base, boolean sign, DList next) { 88 cananian 1.1.2.1 this.base = base; this.sign = sign; this.next = next; 89 cananian 1.1.2.4 // this is the rule for canonicalization: 90 cananian 1.1.2.4 this.canonical = (next == null) || 91 cananian 1.1.2.4 (next.canonical && base==next.base && sign==next.sign) || 92 cananian 1.1.2.4 (next.canonical && base.compareTo(next.base) < 0); 93 cananian 1.3.2.1 assert base!=null : "Null base pointer in DList."; 94 cananian 1.1.2.1 } 95 cananian 1.1.2.1 96 cananian 1.1.2.5 /** Returns a human-readable description of this <code>DList</code>. */ 97 cananian 1.1.2.5 public String toString() { 98 cananian 1.1.2.5 return "<k>"+toString(canonicalize()); 99 cananian 1.1.2.5 } 100 cananian 1.1.2.5 // helper function for toString(). 101 cananian 1.1.2.5 private static String toString(DList dl) { 102 cananian 1.1.2.5 if (dl==null) return ""; 103 cananian 1.1.2.5 else return (dl.sign?"+":"-") + dl.base + toString(dl.next); 104 cananian 1.1.2.5 } 105 cananian 1.1.2.4 /** Equality test. Compares the canonical forms of the 106 cananian 1.1.2.4 * <code>DList</code>s for strict equality. */ 107 cananian 1.1.2.4 public boolean equals(Object o) { 108 cananian 1.1.2.4 if (!canonical) return canonicalize().equals(o); 109 cananian 1.1.2.4 if (!(o instanceof DList)) return false; 110 cananian 1.1.2.4 DList dl = (DList) o; 111 cananian 1.1.2.4 if (!dl.canonical) return this.equals(dl.canonicalize()); 112 cananian 1.1.2.4 if (this.base != dl.base) return false; 113 cananian 1.1.2.4 if (this.sign != dl.sign) return false; 114 cananian 1.1.2.4 if (this.next == null || dl.next == null) 115 cananian 1.1.2.4 return this.next == dl.next; 116 cananian 1.1.2.4 else return this.next.equals(dl.next); 117 cananian 1.1.2.4 } 118 cananian 1.1.2.4 /** Canonicalize a <code>DList</code>. The canonicalized 119 cananian 1.1.2.4 * form of a <code>DList</code> has all components sorted 120 cananian 1.1.2.4 * by <code>Temp</code> (using the natural ordering of 121 cananian 1.1.2.4 * <code>Temp</code>s), and is algebraically simplified 122 cananian 1.1.2.4 * --- that is, components with the same <code>Temp</code> 123 cananian 1.1.2.4 * and opposite signs cancel out. */ 124 cananian 1.1.2.4 public DList canonicalize() { 125 cananian 1.1.2.4 if (canonical) return this; 126 cananian 1.5 List<DList> l = new ArrayList<DList>(); 127 cananian 1.1.2.4 for (DList dl=this; dl!=null; dl=dl.next) 128 cananian 1.1.2.4 l.add(dl); 129 cananian 1.5 Collections.sort(l, new Comparator<DList> () { 130 cananian 1.1.2.4 // reverse order by dl.temp natural ordering. 131 cananian 1.5 public int compare(DList dl1, DList dl2) { 132 cananian 1.1.2.4 int order = dl1.base.compareTo(dl2.base); 133 cananian 1.1.2.4 if (order==0) order = (dl1.sign?1:-1) - (dl2.sign?1:-1); 134 cananian 1.1.2.4 return -order; // reverse 135 cananian 1.1.2.4 } 136 cananian 1.1.2.4 }); 137 cananian 1.1.2.4 DList result = null; 138 cananian 1.5 for (Iterator<DList> it=l.iterator(); it.hasNext(); it.next()) { 139 cananian 1.5 DList dl = it.next(); 140 cananian 1.1.2.4 if (result!=null && 141 cananian 1.1.2.4 result.base == dl.base && 142 cananian 1.1.2.4 result.sign != dl.sign) 143 cananian 1.1.2.4 result = result.next; // cancel out component. 144 cananian 1.1.2.4 else 145 cananian 1.1.2.4 result = new DList(dl.base, dl.sign, result); 146 cananian 1.1.2.4 } 147 cananian 1.3.2.1 assert result!=null && result.canonical; 148 cananian 1.1.2.4 return result; 149 cananian 1.1.2.4 } 150 cananian 1.1.2.4 151 cananian 1.1.2.6 /** Returns a clean copy of this <code>DList</code>. Does 152 cananian 1.1.2.6 * not rename <code>Temp</code>s in any way. */ 153 cananian 1.1.2.1 public static DList clone(DList dlist) { 154 cananian 1.1.2.1 if (dlist==null) return null; 155 cananian 1.1.2.1 else return new DList(dlist.base, dlist.sign, clone(dlist.next)); 156 cananian 1.1.2.1 } 157 cananian 1.1.2.1 158 cananian 1.1.2.1 /** Returns a new <code>DList</code> with the <code>Temp</code>s 159 cananian 1.1.2.1 * renamed by the supplied mapping */ 160 cananian 1.1.2.1 public static DList rename(DList dlist, TempMap tempMap) 161 cananian 1.1.2.1 { 162 cananian 1.1.2.1 if (dlist==null) return null; 163 cananian 1.1.2.1 else return new DList 164 cananian 1.1.2.6 ( tempMap==null ? dlist.base : tempMap.tempMap(dlist.base), 165 cananian 1.1.2.1 dlist.sign, 166 cananian 1.1.2.1 rename(dlist.next, tempMap)); 167 cananian 1.1.2.1 } 168 cananian 1.1.2.1 } 169 cananian 1.2 }