1 cananian 1.1.2.1 // TreeToC.java, created Thu Jun 22 14:23:38 2000 by cananian 2 cananian 1.1.2.1 // Copyright (C) 2000 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.Backend.PreciseC; 5 cananian 1.1.2.1 6 cananian 1.1.2.15 import harpoon.Analysis.Liveness; 7 cananian 1.1.2.15 import harpoon.Analysis.Maps.Derivation; 8 cananian 1.20 import harpoon.Analysis.Reachable; 9 cananian 1.1.2.15 import harpoon.ClassFile.HClass; 10 cananian 1.1.2.2 import harpoon.ClassFile.HCode; 11 cananian 1.20 import harpoon.ClassFile.HCodeElement; 12 cananian 1.1.2.2 import harpoon.ClassFile.HData; 13 cananian 1.20 import harpoon.ClassFile.HDataElement; 14 cananian 1.1.2.15 import harpoon.IR.Properties.UseDefer; 15 cananian 1.1.2.2 import harpoon.IR.Tree.ALIGN; 16 cananian 1.1.2.2 import harpoon.IR.Tree.BINOP; 17 cananian 1.1.2.2 import harpoon.IR.Tree.Bop; 18 cananian 1.1.2.2 import harpoon.IR.Tree.CALL; 19 cananian 1.1.2.2 import harpoon.IR.Tree.CJUMP; 20 cananian 1.1.2.2 import harpoon.IR.Tree.CONST; 21 cananian 1.1.2.2 import harpoon.IR.Tree.DATUM; 22 cananian 1.1.2.2 import harpoon.IR.Tree.ESEQ; 23 cananian 1.1.2.2 import harpoon.IR.Tree.EXPR; 24 cananian 1.1.2.2 import harpoon.IR.Tree.Exp; 25 cananian 1.1.2.2 import harpoon.IR.Tree.ExpList; 26 cananian 1.1.2.15 import harpoon.IR.Tree.INVOCATION; 27 cananian 1.1.2.2 import harpoon.IR.Tree.JUMP; 28 cananian 1.1.2.2 import harpoon.IR.Tree.LABEL; 29 cananian 1.1.2.2 import harpoon.IR.Tree.MEM; 30 cananian 1.1.2.2 import harpoon.IR.Tree.METHOD; 31 cananian 1.1.2.2 import harpoon.IR.Tree.MOVE; 32 cananian 1.1.2.2 import harpoon.IR.Tree.NAME; 33 cananian 1.1.2.2 import harpoon.IR.Tree.NATIVECALL; 34 cananian 1.1.2.2 import harpoon.IR.Tree.PreciselyTyped; 35 cananian 1.1.2.2 import harpoon.IR.Tree.RETURN; 36 cananian 1.1.2.2 import harpoon.IR.Tree.SEGMENT; 37 cananian 1.1.2.2 import harpoon.IR.Tree.SEQ; 38 cananian 1.1.2.2 import harpoon.IR.Tree.TEMP; 39 cananian 1.1.2.2 import harpoon.IR.Tree.THROW; 40 cananian 1.1.2.2 import harpoon.IR.Tree.Tree; 41 cananian 1.1.2.15 import harpoon.IR.Tree.TreeDerivation; 42 cananian 1.1.2.2 import harpoon.IR.Tree.TreeVisitor; 43 cananian 1.1.2.2 import harpoon.IR.Tree.Type; 44 cananian 1.1.2.2 import harpoon.IR.Tree.Typed; 45 cananian 1.1.2.2 import harpoon.IR.Tree.UNOP; 46 cananian 1.1.2.2 import harpoon.IR.Tree.Uop; 47 cananian 1.1.2.2 import harpoon.Temp.Label; 48 cananian 1.1.2.1 import harpoon.Temp.LabelList; 49 cananian 1.1.2.15 import harpoon.Temp.Temp; 50 cananian 1.21 import net.cscott.jutil.ReverseIterator; 51 cananian 1.1.2.6 import harpoon.Util.Util; 52 cananian 1.1.2.2 import java.io.OutputStream; 53 cananian 1.1.2.2 import java.io.PrintWriter; 54 cananian 1.1.2.3 import java.io.StringWriter; 55 cananian 1.1.2.2 import java.io.Writer; 56 cananian 1.8 import java.util.Arrays; 57 cananian 1.8 import java.util.Collection; 58 cananian 1.1.2.15 import java.util.Collections; 59 cananian 1.1.2.3 import java.util.HashMap; 60 cananian 1.1.2.3 import java.util.HashSet; 61 cananian 1.1.2.3 import java.util.Iterator; 62 cananian 1.1.2.3 import java.util.Map; 63 cananian 1.1.2.3 import java.util.Set; 64 cananian 1.9 import java.util.TreeSet; 65 cananian 1.1.2.1 /** 66 cananian 1.1.2.1 * <code>TreeToC</code> converts Tree form to C code (used as a 67 cananian 1.1.2.1 * "portable assembly language"). 68 cananian 1.1.2.1 * 69 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 70 cananian 1.22 * @version $Id: TreeToC.java,v 1.22 2004/02/08 03:20:54 cananian Exp $ 71 cananian 1.1.2.1 */ 72 cananian 1.1.2.9 public class TreeToC extends java.io.PrintWriter { 73 cananian 1.12 // Support losing platforms (like, say, AIX) where multiple segments 74 cananian 1.12 // in the object file are not permitted. In that case, wrap all 75 cananian 1.12 // data structures/code in #ifdef SECTION_xxx so that we can do the 76 cananian 1.12 // proper grouping ourselves, the hard way. 77 cananian 1.12 private static boolean NO_SECTION_SUPPORT= 78 cananian 1.12 Boolean.getBoolean("harpoon.precisec.no_sections"); 79 cananian 1.12 80 cananian 1.1.2.9 private TranslationVisitor tv; 81 cananian 1.1.2.1 82 cananian 1.1.2.1 /** Creates a <code>TreeToC</code>. */ 83 cananian 1.1.2.9 public TreeToC(Writer out) { 84 cananian 1.1.2.9 super(out); 85 cananian 1.1.2.9 this.tv = new TranslationVisitor(); 86 cananian 1.1.2.1 } 87 cananian 1.1.2.30 // XXX: The TempVisitor approach fails when a single temp may be 88 cananian 1.1.2.30 // assigned values of more than one type. Be careful never to 89 cananian 1.1.2.30 // generate tree form where this happens. (Else, we could use 90 cananian 1.1.2.30 // a reaching-def analysis to associate the "proper" reaching 91 cananian 1.1.2.30 // type with every temp, but that's too much work for me at the 92 cananian 1.1.2.30 // moment. Remember: laziness is one of a good programmer's 93 cananian 1.1.2.30 // cardinal virtues. --CSA 9-jul-2001 94 cananian 1.1.2.15 public void translate(HCode hc) { 95 cananian 1.1.2.15 harpoon.IR.Tree.Code c = (harpoon.IR.Tree.Code) hc; 96 cananian 1.1.2.15 Tree root = (Tree)c.getRootElement(); 97 cananian 1.1.2.15 tv.ud = c.getUseDefer(); 98 cananian 1.1.2.15 tv.live = new harpoon.Analysis.DataFlow.LiveVars 99 cananian 1.1.2.15 (c, c.getGrapher(), tv.ud, Collections.EMPTY_SET); 100 cananian 1.1.2.15 tv.tempv = new TempVisitor(root, c.getTreeDerivation()); 101 cananian 1.1.2.19 tv.inh = new IdentifyNoHandler(c); 102 cananian 1.20 tv.re = new Reachable(c, c.getGrapher()); 103 cananian 1.1.2.15 translate(root); 104 cananian 1.1.2.15 tv.ud = null; 105 cananian 1.1.2.15 tv.live = null; 106 cananian 1.1.2.15 tv.tempv = null; 107 cananian 1.1.2.19 tv.inh = null; 108 cananian 1.20 tv.re = null; 109 cananian 1.1.2.15 } 110 cananian 1.1.2.9 public void translate(HData hd) { translate((Tree)hd.getRootElement()); } 111 cananian 1.1.2.9 private void translate(Tree t) { 112 cananian 1.1.2.9 tv.switchto(tv.NONE); 113 cananian 1.1.2.14 if (t!=null) { tv.lv=new LabelVisitor(t); tv.trans(t); } 114 cananian 1.1.2.1 } 115 cananian 1.1.2.9 public void close() { 116 cananian 1.1.2.9 tv.switchto(tv.NONE); 117 cananian 1.1.2.9 this.println("#include <precisec.h>"); 118 cananian 1.1.2.9 // collect symbol declarations. 119 cananian 1.1.2.9 tv.emitSymbols(this); 120 cananian 1.1.2.9 // now all the code & data 121 cananian 1.1.2.9 tv.emitOutput(this); 122 cananian 1.1.2.9 // okay, now (really) flush and close. 123 cananian 1.1.2.9 super.close(); 124 cananian 1.1.2.1 } 125 cananian 1.1.2.15 /** TempVisitor collects the types of temps */ 126 cananian 1.1.2.15 private static class TempVisitor extends TreeVisitor { 127 cananian 1.1.2.15 public final Map objectTemps = new HashMap(); 128 cananian 1.1.2.15 private final TreeDerivation treederiv; 129 cananian 1.1.2.15 public TempVisitor(Tree t, TreeDerivation treederiv) { 130 cananian 1.1.2.15 this.treederiv = treederiv; 131 cananian 1.1.2.15 t.accept(this); 132 cananian 1.1.2.15 } 133 cananian 1.1.2.15 public void visit(Tree t) { 134 cananian 1.1.2.15 for (Tree st=t.getFirstChild(); st!=null; st=st.getSibling()) 135 cananian 1.1.2.15 st.accept(this); 136 cananian 1.1.2.15 } 137 cananian 1.1.2.15 public void visit(TEMP t) { 138 cananian 1.1.2.15 HClass hc = treederiv.typeMap(t); 139 cananian 1.1.2.15 if (hc==null || !hc.isPrimitive()) 140 cananian 1.1.2.15 objectTemps.put(t.temp, treederiv.derivation(t)); 141 cananian 1.1.2.15 } 142 cananian 1.1.2.15 } 143 cananian 1.1.2.14 /** LabelVisitor identifies the method-local labels. */ 144 cananian 1.1.2.14 private static class LabelVisitor extends TreeVisitor { 145 cananian 1.1.2.17 public final Set method_labels = new HashSet(); 146 cananian 1.1.2.14 public final Set local_code_labels = new HashSet(); 147 cananian 1.1.2.14 public final Set local_table_labels = new HashSet(); 148 cananian 1.1.2.14 private boolean seenMethod = false; 149 cananian 1.1.2.17 LabelList last_labels=null; 150 cananian 1.1.2.14 public LabelVisitor(Tree t) { t.accept(this); } 151 cananian 1.1.2.14 public void visit(Tree e) { 152 cananian 1.1.2.17 if (last_labels!=null) { 153 cananian 1.1.2.17 if (seenMethod) 154 cananian 1.1.2.17 local_code_labels.addAll(LabelList.toList(last_labels)); 155 cananian 1.1.2.17 last_labels=null; 156 cananian 1.1.2.14 } 157 cananian 1.1.2.14 } 158 cananian 1.1.2.14 public void visit(SEQ e) { 159 cananian 1.1.2.14 e.getLeft().accept(this); 160 cananian 1.1.2.14 e.getRight().accept(this); 161 cananian 1.1.2.14 } 162 cananian 1.1.2.17 public void visit(METHOD e) { 163 cananian 1.1.2.17 seenMethod = true; 164 cananian 1.1.2.17 method_labels.addAll(LabelList.toList(last_labels)); 165 cananian 1.1.2.17 last_labels=null; 166 cananian 1.1.2.17 } 167 cananian 1.1.2.17 public void visit(LABEL e) { 168 cananian 1.1.2.17 last_labels=new LabelList(e.label, last_labels); 169 cananian 1.1.2.17 } 170 cananian 1.1.2.14 public void visit(DATUM e) { 171 cananian 1.1.2.17 if (last_labels!=null) { 172 cananian 1.1.2.17 if (seenMethod) 173 cananian 1.1.2.17 local_table_labels.addAll(LabelList.toList(last_labels)); 174 cananian 1.1.2.17 last_labels=null; 175 cananian 1.1.2.14 } 176 cananian 1.1.2.14 } 177 cananian 1.1.2.14 } 178 cananian 1.1.2.14 /** TranslationVisitor does the real work. */ 179 cananian 1.1.2.1 private static class TranslationVisitor extends TreeVisitor { 180 cananian 1.1.2.1 // default case throws error: we should handle each tree specifically. 181 cananian 1.1.2.1 public void visit(Tree e) { 182 cananian 1.1.2.1 throw new Error("Unmatched Tree: "+e); 183 cananian 1.1.2.1 } 184 cananian 1.1.2.3 // StringWriters and PrintWriters for the translation. 185 cananian 1.1.2.3 // four output sections: gbl_decls, meth_decls, meth_body, gbl_data 186 cananian 1.1.2.6 /** Method declaration and local variables */ 187 cananian 1.1.2.6 private final int MD=0; 188 cananian 1.1.2.6 /** Method body. */ 189 cananian 1.1.2.6 private final int MB=1; 190 cananian 1.1.2.6 /** Data declarations (as struct) */ 191 cananian 1.1.2.6 private final int DD=2; 192 cananian 1.1.2.6 /** Data initializations. */ 193 cananian 1.1.2.6 private final int DI=3; 194 cananian 1.1.2.6 /** Number of sections */ 195 cananian 1.1.2.6 private final int SECTIONS=4; 196 cananian 1.1.2.6 197 cananian 1.1.2.3 private StringWriter[] swa = new StringWriter[SECTIONS]; 198 cananian 1.1.2.3 private PrintWriter[] pwa = new PrintWriter[SECTIONS]; 199 cananian 1.1.2.1 private PrintWriter pw; 200 cananian 1.1.2.3 TranslationVisitor() { 201 cananian 1.1.2.3 for (int i=0; i<SECTIONS; i++) { 202 cananian 1.1.2.3 swa[i] = new StringWriter(); 203 cananian 1.1.2.3 pwa[i] = new PrintWriter(swa[i]); 204 cananian 1.1.2.3 } 205 cananian 1.1.2.6 pw = null; 206 cananian 1.1.2.3 } 207 cananian 1.1.2.15 // support liveness info for *precise* gc. 208 cananian 1.1.2.15 Liveness live = null; 209 cananian 1.1.2.15 UseDefer ud = null; 210 cananian 1.1.2.15 TempVisitor tempv = null; 211 cananian 1.1.2.19 // support no-handler optimization 212 cananian 1.1.2.19 IdentifyNoHandler inh = null; 213 cananian 1.20 // note reachability, to work around unreachable code. 214 cananian 1.20 Reachable re = null; 215 cananian 1.1.2.15 216 cananian 1.1.2.5 // keep track of current alignment, section, method, etc. 217 cananian 1.1.2.6 ALIGN align = null; 218 cananian 1.1.2.5 SEGMENT segment = null; 219 cananian 1.1.2.5 METHOD method = null; 220 cananian 1.1.2.6 LABEL label = null; 221 cananian 1.1.2.6 int field_counter = 0; 222 cananian 1.1.2.6 223 cananian 1.1.2.6 // switch from one mode to the next. 224 cananian 1.1.2.9 static final int NONE = 0; 225 cananian 1.1.2.9 static final int DATA = 1; 226 cananian 1.1.2.9 static final int CODE = 2; 227 cananian 1.1.2.14 static final int CODETABLE = 3; 228 cananian 1.1.2.6 int current_mode = NONE; 229 cananian 1.1.2.6 void switchto(int mode) { 230 cananian 1.1.2.6 switch(current_mode) { 231 cananian 1.1.2.6 case CODE: 232 cananian 1.1.2.14 if (mode==CODETABLE) break; // postpone flush. 233 cananian 1.1.2.6 flushAndAppend(MD); 234 cananian 1.1.2.6 pwa[MB].println("}"); 235 cananian 1.12 if (NO_SECTION_SUPPORT) pwa[MB].println("#endif"); 236 cananian 1.1.2.6 flushAndAppend(MB); 237 cananian 1.1.2.6 temps_seen.clear(); 238 cananian 1.1.2.6 break; 239 cananian 1.1.2.14 case CODETABLE: // flush to CODE. 240 cananian 1.3.2.1 assert mode==CODE; 241 cananian 1.1.2.14 pwa[DI].println("};"); 242 cananian 1.1.2.14 flushAndAppendTo(DD, MD); 243 cananian 1.1.2.14 flushAndAppendTo(DI, MD); 244 cananian 1.1.2.14 break; 245 cananian 1.1.2.6 case DATA: 246 cananian 1.13 assert field_counter>0 : "gcc will put this guy in .bss "+ 247 cananian 1.13 "regardless of the specified section, which will likely "+ 248 cananian 1.13 "break your build."; 249 cananian 1.1.2.6 pwa[DI].println("};"); 250 cananian 1.12 if (NO_SECTION_SUPPORT) pwa[DI].println("#endif"); 251 cananian 1.1.2.6 flushAndAppend(DD); 252 cananian 1.1.2.6 flushAndAppend(DI); 253 cananian 1.1.2.6 break; 254 cananian 1.1.2.6 default: break; 255 cananian 1.1.2.6 } 256 cananian 1.1.2.6 current_mode = mode; 257 cananian 1.1.2.6 switch(current_mode) { 258 cananian 1.1.2.6 case CODE: 259 cananian 1.1.2.14 pw = pwa[MB]; 260 cananian 1.1.2.6 break; 261 cananian 1.1.2.14 case CODETABLE: 262 cananian 1.1.2.6 case DATA: 263 cananian 1.1.2.6 field_counter = 0; 264 cananian 1.1.2.6 pw = pwa[DI]; 265 cananian 1.1.2.6 break; 266 cananian 1.1.2.6 default: break; 267 cananian 1.1.2.6 } 268 cananian 1.1.2.6 } 269 cananian 1.1.2.6 StringBuffer output = new StringBuffer(); 270 cananian 1.1.2.6 void flushAndAppend(int which) { 271 cananian 1.1.2.6 pwa[which].flush(); 272 cananian 1.1.2.6 StringBuffer sb = swa[which].getBuffer(); 273 cananian 1.1.2.6 output.append(sb); 274 cananian 1.1.2.6 sb.setLength(0); 275 cananian 1.1.2.6 } 276 cananian 1.1.2.14 void flushAndAppendTo(int from, int to) { 277 cananian 1.1.2.14 pwa[from].flush(); 278 cananian 1.1.2.14 StringBuffer sb = swa[from].getBuffer(); 279 cananian 1.1.2.14 pwa[to].print(sb); 280 cananian 1.1.2.14 sb.setLength(0); 281 cananian 1.1.2.14 } 282 cananian 1.1.2.5 283 cananian 1.1.2.3 /** these are the symbols referenced (and declarations for them) */ 284 cananian 1.1.2.3 Map sym2decl = new HashMap(); 285 cananian 1.1.2.10 { /* gcc complains if we don't declare certain symbols "properly". */ 286 cananian 1.1.2.10 sym2decl.put(new Label("memset"), 287 cananian 1.1.2.10 "extern void *memset(void *,int,size_t);"); 288 cananian 1.1.2.17 sym2decl.put(new Label("alloca"), 289 cananian 1.1.2.17 "extern void *alloca(size_t);"); 290 cananian 1.1.2.32 /* we use puts in translating the DEBUG quad */ 291 cananian 1.1.2.32 sym2decl.put(new Label("puts"), 292 cananian 1.1.2.32 "int puts(const char *s);"); 293 cananian 1.1.2.14 /* also, we need to use FNI_GetJNIEnv() at points. */ 294 cananian 1.1.2.14 sym2decl.put(new Label("FNI_GetJNIEnv"), 295 cananian 1.1.2.14 "extern JNIEnv *FNI_GetJNIEnv(void);"); 296 kkz 1.1.2.33 sym2decl.put(new Label("generational_write_barrier"), 297 kkz 1.1.2.33 "extern void generational_write_barrier"+ 298 kkz 1.1.2.33 "(jobject_unwrapped *);"); 299 cananian 1.1.2.10 } 300 cananian 1.1.2.17 /** functions we have exact prototypes for */ 301 cananian 1.1.2.17 static Set exactproto = new HashSet(); 302 kkz 1.1.2.33 static { exactproto.add("memset"); exactproto.add("alloca"); 303 cananian 1.14 exactproto.add("generational_write_barrier"); 304 cananian 1.14 } 305 cananian 1.1.2.17 306 cananian 1.1.2.10 /** these are the *local* labels which are defined *inside functions* 307 cananian 1.1.2.10 * in this file. */ 308 cananian 1.1.2.14 LabelVisitor lv=null; 309 cananian 1.1.2.9 310 cananian 1.1.2.9 void emitSymbols(PrintWriter pw) { 311 cananian 1.8 // sort the symbols so that the output is stable across runs. 312 cananian 1.8 Collection c = sym2decl.values(); 313 cananian 1.8 String[] syms = (String[]) c.toArray(new String[c.size()]); 314 cananian 1.8 Arrays.sort(syms); 315 cananian 1.8 for (int i=0; i<syms.length; i++) 316 cananian 1.8 pw.println(syms[i]); 317 cananian 1.1.2.1 } 318 cananian 1.1.2.9 void emitOutput(PrintWriter pw) { 319 cananian 1.1.2.9 pw.print(output); 320 cananian 1.1.2.9 } 321 cananian 1.1.2.24 // make a string "safe". This is made necessary by obfuscators. 322 cananian 1.1.2.24 private static String safe(String s) { 323 cananian 1.1.2.24 char[] ca = s.toCharArray(); 324 cananian 1.1.2.24 for (int i=0; i<ca.length; i++) 325 cananian 1.1.2.24 if (Character.isISOControl(ca[i])) ca[i]='#'; 326 cananian 1.1.2.24 return new String(ca); 327 cananian 1.1.2.24 } 328 cananian 1.1.2.9 329 cananian 1.1.2.1 // useful line number update function. 330 cananian 1.1.2.25 private boolean EMIT_LINE_DIRECTIVES= 331 cananian 1.1.2.25 Boolean.getBoolean("harpoon.precisec.emit_line_directives"); 332 salcianu 1.1.2.26 // the line "directives" will be just comments containing the 333 salcianu 1.1.2.26 // line numbers 334 salcianu 1.1.2.26 private boolean EMIT_FAKE_LINE_DIRECTIVES= 335 salcianu 1.1.2.26 Boolean.getBoolean("harpoon.precisec.emit_fake_line_directives"); 336 cananian 1.1.2.21 private int suppress_directives=0; 337 cananian 1.1.2.1 private String last_file = null; 338 cananian 1.1.2.1 private int last_line = 0; 339 cananian 1.1.2.1 private void updateLine(Tree e) { 340 cananian 1.1.2.21 if (!EMIT_LINE_DIRECTIVES || suppress_directives>0) return; 341 cananian 1.1.2.13 if (e instanceof SEQ) return; 342 cananian 1.1.2.13 if (pw==null) return; 343 cananian 1.1.2.24 String curr_file = safe(e.getSourceFile()); 344 cananian 1.1.2.1 int curr_line = e.getLineNumber(); 345 cananian 1.1.2.13 boolean files_match = 346 cananian 1.1.2.13 last_file==null ? curr_file==null :last_file.equals(curr_file); 347 cananian 1.1.2.13 if (last_line == curr_line && files_match) return; 348 cananian 1.1.2.1 pw.println(); 349 cananian 1.1.2.13 boolean line_needed = !(last_line == curr_line-1 && files_match); 350 cananian 1.1.2.1 last_file = curr_file; 351 cananian 1.1.2.1 last_line = curr_line; 352 cananian 1.1.2.13 if (line_needed) emitLineDirective(!files_match); 353 cananian 1.1.2.13 } 354 cananian 1.1.2.13 private void emitLineDirective(boolean emitFile) { 355 cananian 1.1.2.21 if (!EMIT_LINE_DIRECTIVES || suppress_directives>0) return; 356 cananian 1.1.2.13 if (last_file==null && last_line==0) return; 357 cananian 1.1.2.13 pw.println(); 358 salcianu 1.1.2.26 359 salcianu 1.1.2.26 if(EMIT_FAKE_LINE_DIRECTIVES) // just comments - useful for debug 360 salcianu 1.1.2.26 pw.print("/* line " + last_line); 361 salcianu 1.1.2.26 else 362 salcianu 1.1.2.26 pw.print("#line " + last_line); 363 salcianu 1.1.2.26 364 cananian 1.1.2.13 if (emitFile) pw.print(" \""+last_file+"\""); 365 salcianu 1.1.2.26 if(EMIT_FAKE_LINE_DIRECTIVES) 366 salcianu 1.1.2.26 pw.print(" */"); 367 cananian 1.1.2.13 pw.println(); 368 cananian 1.1.2.13 } 369 cananian 1.1.2.13 private void nl() { 370 cananian 1.1.2.13 if ((!EMIT_LINE_DIRECTIVES) || 371 cananian 1.1.2.13 (last_file==null && last_line==0)) 372 cananian 1.1.2.13 pw.println(); 373 cananian 1.1.2.13 else 374 cananian 1.1.2.13 pw.print(" "); 375 cananian 1.1.2.1 } 376 cananian 1.20 private void trans(Tree e) { 377 cananian 1.20 if (current_mode==CODE && e instanceof harpoon.IR.Tree.Stm && 378 cananian 1.20 !(e instanceof HDataElement) && !re.isReachable(e)) { 379 cananian 1.20 //System.err.println("SKIPPING "+e+" in "+e.getFactory()); 380 cananian 1.20 return; // skip unreachable *code*. 381 cananian 1.20 } 382 cananian 1.20 updateLine(e); e.accept(this); 383 cananian 1.20 } 384 cananian 1.1.2.8 private static int sizeof(Typed t) { 385 cananian 1.1.2.8 if (t instanceof PreciselyTyped) { 386 cananian 1.1.2.8 PreciselyTyped pt = (PreciselyTyped) t; 387 cananian 1.1.2.8 if (pt.isSmall()) 388 cananian 1.1.2.8 return (pt.bitwidth()+7) / 8; 389 cananian 1.1.2.8 } 390 cananian 1.1.2.8 return t.isDoubleWord() ? 8 : 4; 391 cananian 1.1.2.8 } 392 cananian 1.1.2.5 private static String ctype(Typed t) { 393 cananian 1.1.2.1 String result; 394 cananian 1.1.2.1 if (t instanceof PreciselyTyped) { 395 cananian 1.1.2.1 PreciselyTyped pt = (PreciselyTyped) t; 396 cananian 1.1.2.1 if (pt.isSmall()) 397 cananian 1.19 return (pt.signed()?"int":"uint")+pt.bitwidth()+"_t"; 398 cananian 1.1.2.1 } 399 cananian 1.1.2.1 return ctype(t.type()); 400 cananian 1.1.2.1 } 401 cananian 1.1.2.5 private static String ctype(int type) { 402 cananian 1.1.2.1 if (type==Type.DOUBLE) return "jdouble"; 403 cananian 1.1.2.1 if (type==Type.FLOAT) return "jfloat"; 404 cananian 1.1.2.1 if (type==Type.INT) return "jint"; 405 cananian 1.1.2.1 if (type==Type.LONG) return "jlong"; 406 cananian 1.1.2.5 if (type==Type.POINTER) return "jptr"; 407 cananian 1.1.2.4 throw new Error("unknown type: "+type); 408 cananian 1.1.2.4 } 409 cananian 1.1.2.5 private static String label(Label l) { 410 cananian 1.1.2.2 String r = l.toString(); 411 cananian 1.1.2.2 return r.startsWith(".")?r.substring(1):r; 412 cananian 1.1.2.2 } 413 cananian 1.1.2.16 private String sectionname(SEGMENT s) { 414 cananian 1.1.2.5 switch (s.segtype) { 415 cananian 1.1.2.5 case SEGMENT.TEXT: return ".text"; 416 cananian 1.1.2.5 case SEGMENT.ZERO_DATA: return ".flex.zero"; 417 cananian 1.1.2.16 case SEGMENT.CODE: // gcc is picky about data in code segment. 418 cananian 1.1.2.16 if (current_mode==CODETABLE) return ".flex.code.rw"; 419 cananian 1.1.2.16 // else fall through: 420 cananian 1.1.2.5 default: 421 cananian 1.1.2.5 return ".flex."+s.decode(s.segtype).toLowerCase(); 422 cananian 1.1.2.5 } 423 cananian 1.1.2.5 } 424 cananian 1.12 private String sectionnameDEF(SEGMENT seg) { 425 cananian 1.12 if (seg==null) return "NONE"; 426 cananian 1.12 String s = sectionname(seg); 427 cananian 1.12 while (s.charAt(0)=='.') s=s.substring(1); 428 cananian 1.12 return s.replace('.','_').toUpperCase(); 429 cananian 1.12 } 430 cananian 1.1.2.1 431 cananian 1.1.2.1 // okay, shoot: 432 cananian 1.1.2.1 public void visit(ALIGN e) { 433 cananian 1.1.2.6 this.align = e; 434 cananian 1.1.2.1 } 435 cananian 1.1.2.1 public void visit(BINOP e) { 436 cananian 1.1.2.28 boolean macro=false, funccall=false, andwithptrargs=false; 437 cananian 1.1.2.1 pw.print("("); 438 cananian 1.1.2.23 439 cananian 1.1.2.23 if (e.op==Bop.SHR || e.op==Bop.USHR) { 440 cananian 1.1.2.23 macro=funccall=true; 441 cananian 1.1.2.23 if (e.type()==Type.LONG) 442 cananian 1.1.2.23 pw.print("L"); // macro prefix for long ops. 443 cananian 1.1.2.23 if (e.op==Bop.SHR) pw.print("SHR("); // use macro 444 cananian 1.1.2.23 if (e.op==Bop.USHR) pw.print("USHR("); // use macro 445 cananian 1.1.2.23 } 446 cananian 1.1.2.23 if (e.op==Bop.REM && e.type()==Type.FLOAT) { 447 cananian 1.1.2.23 funccall=true; 448 cananian 1.1.2.23 pw.print("fmodf("); // double remainder == c-lib frem() 449 cananian 1.1.2.23 sym2decl.put(new Label("fmodf"),"float fmodf(float, float);"); 450 cananian 1.1.2.23 } 451 cananian 1.1.2.23 if (e.op==Bop.REM && e.type()==Type.DOUBLE) { 452 cananian 1.1.2.23 funccall=true; 453 cananian 1.1.2.23 pw.print("fmod("); // double remainder == c-lib frem() 454 cananian 1.1.2.23 sym2decl.put(new Label("fmod"),"double fmod(double, double);"); 455 cananian 1.1.2.23 } 456 cananian 1.1.2.27 if (e.op==Bop.AND && e.type()==e.POINTER) { 457 cananian 1.1.2.28 andwithptrargs=true; 458 cananian 1.1.2.27 pw.print("(void *)("); 459 cananian 1.1.2.27 } 460 cananian 1.1.2.23 if (macro) suppress_directives++; 461 cananian 1.1.2.28 if (andwithptrargs) pw.print("(ptroff_t)"); 462 cananian 1.1.2.1 trans(e.getLeft()); 463 cananian 1.1.2.23 if (funccall) pw.print(", "); 464 cananian 1.1.2.23 else switch(e.op) { 465 cananian 1.1.2.1 case Bop.CMPLT: pw.print("<"); break; 466 cananian 1.1.2.1 case Bop.CMPLE: pw.print("<="); break; 467 cananian 1.1.2.1 case Bop.CMPEQ: pw.print("=="); break; 468 cananian 1.1.2.1 case Bop.CMPNE: pw.print("!="); break; 469 cananian 1.1.2.1 case Bop.CMPGE: pw.print(">="); break; 470 cananian 1.1.2.1 case Bop.CMPGT: pw.print(">"); break; 471 cananian 1.1.2.1 case Bop.ADD: pw.print("+"); break; 472 cananian 1.1.2.1 case Bop.MUL: pw.print("*"); break; 473 cananian 1.1.2.1 case Bop.DIV: pw.print("/"); break; 474 cananian 1.1.2.1 case Bop.REM: pw.print("%/*rem*/"); break; 475 cananian 1.1.2.1 case Bop.SHL: pw.print("<<"); break; 476 cananian 1.1.2.1 case Bop.AND: pw.print("&"); break; 477 cananian 1.1.2.1 case Bop.OR: pw.print("|"); break; 478 cananian 1.1.2.1 case Bop.XOR: pw.print("^"); break; 479 cananian 1.1.2.1 default: throw new Error("unknown Bop: "+e); 480 cananian 1.1.2.1 } 481 cananian 1.1.2.28 if (andwithptrargs) pw.print("(ptroff_t)"); 482 cananian 1.1.2.1 trans(e.getRight()); 483 cananian 1.1.2.28 if (funccall||andwithptrargs) pw.print(")"); // close macro/call 484 cananian 1.1.2.23 if (macro) suppress_directives--; 485 cananian 1.1.2.1 pw.print(")"); 486 cananian 1.1.2.1 } 487 cananian 1.1.2.1 public void visit(CALL e) { 488 cananian 1.1.2.15 Set liveo = liveObjects(e); 489 cananian 1.7 pw.print("\t"); emitPush(liveo); pw.print(";"); nl(); 490 cananian 1.1.2.21 suppress_directives++; 491 cananian 1.1.2.19 String nh = inh.requiresHandler(e) ? "" : "_NH"; 492 cananian 1.1.2.5 boolean callv = (e.getRetval()==null); 493 cananian 1.1.2.5 if (callv) { 494 cananian 1.1.2.19 pw.print("\tCALLV"+nh+"("); 495 cananian 1.1.2.5 pw.print("((FUNCPROTOV("); 496 cananian 1.1.2.5 } else { 497 cananian 1.1.2.19 pw.print("\tCALL"+nh+"("+ctype(e.getRetval())+", "); 498 cananian 1.1.2.5 trans(e.getRetval()); 499 cananian 1.1.2.5 pw.print(", ((FUNCPROTO("+ctype(e.getRetval())+", "); 500 cananian 1.1.2.5 } 501 cananian 1.1.2.5 pw.print("(FIRST_PROTO_ARG(void *) "); 502 cananian 1.1.2.4 /* function type cast */ 503 cananian 1.1.2.4 for (ExpList el=e.getArgs(); el!=null; el=el.tail) { 504 cananian 1.1.2.4 pw.print(ctype(el.head)); 505 cananian 1.1.2.4 if (el.tail!=null) pw.print(", "); 506 cananian 1.1.2.4 } 507 cananian 1.1.2.5 pw.print("))) "); 508 cananian 1.1.2.4 /* function expression */ 509 cananian 1.1.2.4 trans(e.getFunc()); 510 cananian 1.1.2.5 pw.print("), (FIRST_CALL_ARG(&&"+label(e.getHandler().label)+") "); 511 cananian 1.1.2.4 for (ExpList el=e.getArgs(); el!=null; el=el.tail) { 512 cananian 1.1.2.4 trans(el.head); 513 cananian 1.1.2.4 if (el.tail!=null) pw.print(", "); 514 cananian 1.1.2.4 } 515 cananian 1.1.2.5 pw.print("), "); 516 cananian 1.1.2.5 trans(e.getRetex()); 517 cananian 1.1.2.15 pw.print(", "+label(e.getHandler().label)); 518 cananian 1.7 pw.print(", "); emitPop(liveo); pw.print(");"); 519 cananian 1.1.2.21 suppress_directives--; 520 cananian 1.1.2.13 nl(); 521 cananian 1.1.2.1 } 522 cananian 1.1.2.1 public void visit(CJUMP e) { 523 cananian 1.1.2.1 pw.print("\tif ("); trans(e.getTest()); pw.print(")"); 524 cananian 1.7 pw.print(" goto "+label(e.iftrue)+";"); 525 cananian 1.7 pw.print(" else goto "+label(e.iffalse)+";"); 526 cananian 1.1.2.13 nl(); 527 cananian 1.1.2.1 } 528 cananian 1.1.2.1 public void visit(CONST e) { 529 cananian 1.1.2.12 if (e.value()==null) { pw.print("NULL"); return; } 530 cananian 1.1.2.12 String val = e.value().toString(); 531 cananian 1.1.2.12 if (e.type()==Type.DOUBLE) { 532 cananian 1.1.2.12 Double d = (Double) e.value(); 533 cananian 1.1.2.12 if (d.isInfinite()) { 534 cananian 1.1.2.12 pw.print("("+(d.doubleValue()<0?"-":"")+"1.0/0.0)"); 535 cananian 1.1.2.12 return; 536 cananian 1.1.2.12 } 537 cananian 1.1.2.12 if (d.isNaN()) { pw.print("(0.0/0.0)"); return; } 538 cananian 1.1.2.12 } 539 cananian 1.1.2.12 if (e.type()==Type.FLOAT) { 540 cananian 1.1.2.12 Float f = (Float) e.value(); 541 cananian 1.1.2.12 if (f.isInfinite()) { 542 cananian 1.1.2.12 pw.print("("+(f.floatValue()<0?"-":"")+"1.0f/0.0f)"); 543 cananian 1.1.2.12 return; 544 cananian 1.1.2.12 } 545 cananian 1.1.2.12 if (f.isNaN()) { pw.print("(0.0f/0.0f)"); return; } 546 cananian 1.1.2.12 } 547 cananian 1.1.2.10 if (e.type()==Type.INT && e.value().intValue()==Integer.MIN_VALUE) 548 cananian 1.1.2.10 val="0x"+Integer.toHexString(e.value().intValue()); 549 cananian 1.1.2.10 if (e.type()==Type.LONG && e.value().longValue()==Long.MIN_VALUE) 550 cananian 1.1.2.10 val="0x"+Long.toHexString(e.value().longValue()); 551 cananian 1.1.2.10 // XXX: assumption that jfloat==float and jlong==long long 552 cananian 1.1.2.10 // this assumption may be erroneous! =( but no way to 553 cananian 1.1.2.10 // 'portably' define constants. 554 cananian 1.1.2.10 if (e.type()==Type.FLOAT) val+="F"; 555 cananian 1.1.2.10 if (e.type()==Type.LONG) val+="LL"; 556 cananian 1.18 /* make strings slightly more readable */ 557 cananian 1.18 if (e.type()==Type.INT && 558 cananian 1.18 e.value().intValue()>=' ' && 559 cananian 1.18 e.value().intValue()<='~' && 560 cananian 1.18 e.value().intValue()!='\'' && 561 cananian 1.18 e.value().intValue()!='\"' && 562 cananian 1.18 e.value().intValue()!='\\') 563 cananian 1.18 val+="/*'"+((char)e.value().intValue())+"'*/"; 564 cananian 1.1.2.10 pw.print(val); 565 cananian 1.1.2.1 } 566 cananian 1.1.2.1 public void visit(DATUM e) { 567 cananian 1.1.2.14 if (current_mode==CODE) 568 cananian 1.1.2.14 startData(CODETABLE, last_label, false); 569 cananian 1.1.2.8 struct_size += sizeof(e.getData()); 570 cananian 1.1.2.8 // alignment constraints mean we ought to start a new struct. 571 cananian 1.1.2.8 // so does exceeding a struct size of 32 bytes (this is a 572 cananian 1.1.2.8 // very odd gcc oddity, where too-large structs are aligned 573 cananian 1.1.2.8 // to a 32-byte boundary). Also if we haven't entered the 574 cananian 1.1.2.8 // data mode via a label yet, we should make up a label and do so. 575 cananian 1.17 // NOTE that we actually make our maximum struct size 24 bytes, 576 cananian 1.17 // so that we always generate 8-byte aligned structs when 577 cananian 1.17 // possible. This is because IRIX will eight-byte align 578 cananian 1.17 // every struct, whether we ask it to or not. =( CSA 2003-10-06 579 cananian 1.1.2.14 if (current_mode != CODETABLE /* no restrictions here */ && 580 cananian 1.17 (current_mode==NONE || struct_size > 24 || this.align!=null)){ 581 cananian 1.1.2.14 startData(current_mode==NONE ? DATA : current_mode, 582 cananian 1.1.2.14 new Label(), false); 583 cananian 1.1.2.8 struct_size += sizeof(e.getData()); 584 cananian 1.1.2.8 } 585 cananian 1.1.2.6 pwa[DD].print("\t"+ctype(e.getData())+" "); 586 cananian 1.1.2.6 pwa[DD].print("f"+(field_counter++)); 587 cananian 1.1.2.6 pwa[DD].print(" __attribute__ ((packed))"); 588 cananian 1.1.2.6 if (align!=null) 589 cananian 1.1.2.6 pwa[DD].print(" __attribute__ ((aligned (" + 590 cananian 1.1.2.6 this.align.alignment + ")))"); 591 cananian 1.1.2.6 this.align=null; // clear alignment. 592 cananian 1.1.2.6 pwa[DD].println(";"); 593 cananian 1.1.2.13 pw.print("\t"); trans(e.getData()); pw.print(","); nl(); 594 cananian 1.1.2.1 } 595 cananian 1.1.2.1 public void visit(ESEQ e) { 596 cananian 1.1.2.1 throw new Error("Non-canonical tree form."); 597 cananian 1.1.2.1 } 598 cananian 1.1.2.1 public void visit(EXPR e) { 599 cananian 1.7 pw.print("\t"); trans(e.getExp()); pw.print(";"); nl(); 600 cananian 1.1.2.1 } 601 cananian 1.1.2.1 public void visit(JUMP e) { 602 cananian 1.1.2.1 pw.print("\tgoto "); 603 cananian 1.1.2.1 Exp exp = e.getExp(); 604 cananian 1.1.2.1 if (exp instanceof NAME) 605 cananian 1.1.2.3 visit(((NAME)exp), false/*don't take address*/); 606 cananian 1.1.2.1 else { pw.print("*("); trans(exp); pw.print(")"); } 607 cananian 1.1.2.13 pw.print("; /* targets: "+LabelList.toList(e.targets)+" */"); 608 cananian 1.1.2.13 nl(); 609 cananian 1.1.2.1 } 610 cananian 1.1.2.14 Label last_label; 611 cananian 1.1.2.1 public void visit(LABEL e) { 612 cananian 1.1.2.14 // if we're outputting an inline table, switch back to regular 613 cananian 1.1.2.14 // code mode. 614 cananian 1.1.2.14 if (current_mode==CODETABLE) switchto(CODE); 615 cananian 1.1.2.10 if (current_mode==CODE) { 616 cananian 1.1.2.14 if (lv.local_code_labels.contains(e.label)) { 617 cananian 1.1.2.14 pw.print(label(e.label)+":"); nl(); 618 cananian 1.3.2.1 } else assert lv.local_table_labels.contains(e.label); 619 cananian 1.13 } else if (!lv.method_labels.contains(e.label)) { 620 cananian 1.13 if (current_mode==DATA && field_counter==0) { 621 cananian 1.13 // two labels back-to-back. Treat this one as an 622 cananian 1.13 // alias. 623 cananian 1.13 sym2decl.put(e.label, 624 cananian 1.13 "extern void * "+label(e.label)+ 625 cananian 1.13 " __attribute__ "+ 626 cananian 1.13 "((alias(\""+label(last_label)+"\")));"); 627 cananian 1.13 return; 628 cananian 1.13 } else { 629 cananian 1.13 startData(DATA, e.label, e.exported); 630 cananian 1.13 } 631 cananian 1.13 } 632 cananian 1.1.2.14 last_label=e.label; 633 cananian 1.1.2.8 } 634 cananian 1.1.2.8 private int struct_size; 635 cananian 1.1.2.14 public void startData(int mode, Label l, boolean exported) { 636 cananian 1.1.2.14 switchto(mode); 637 cananian 1.12 // without section support, sections are going to be compiled 638 cananian 1.12 // separately, so force exported to be true. 639 cananian 1.13 if (NO_SECTION_SUPPORT && mode!=CODETABLE) exported=true; 640 cananian 1.13 assert (mode==CODETABLE ? !exported : true) : 641 cananian 1.13 "non-static symbols don't work well on the stack."; 642 cananian 1.1.2.14 if (!lv.local_table_labels.contains(l)) 643 cananian 1.1.2.14 sym2decl.put(l, (exported?"extern ":"static ") + 644 cananian 1.1.2.14 "struct "+label(l)+" "+label(l)+";"); 645 cananian 1.12 // wrap this data structure in an #ifdef if no decent 646 cananian 1.12 // section support 647 cananian 1.12 if (NO_SECTION_SUPPORT && mode!=CODETABLE) 648 cananian 1.12 pwa[DD].println("#ifdef SECTION_" + 649 cananian 1.12 sectionnameDEF(this.segment)); 650 cananian 1.1.2.8 struct_size = 0; 651 cananian 1.1.2.8 if (!exported) pwa[DD].print("static "); 652 cananian 1.1.2.8 pwa[DD].println("struct "+label(l)+" {"); 653 cananian 1.1.2.8 pwa[DI].print("} __attribute__ ((packed)) "); 654 cananian 1.1.2.8 pwa[DI].print(label(l)); 655 cananian 1.1.2.8 if (this.align!=null) 656 cananian 1.1.2.8 pwa[DI].print(" __attribute__ ((aligned (" + 657 cananian 1.1.2.8 this.align.alignment + ")))"); 658 cananian 1.18 else /* this works around a gcc/MIPS bug, where structures */ 659 cananian 1.18 /* are 8-byte aligned unless you ask them not to be. */ 660 cananian 1.18 pwa[DI].print(" __attribute__ ((aligned (4)))"); 661 cananian 1.1.2.8 this.align=null; // clear alignment. 662 cananian 1.1.2.19 // older versions of gcc won't allow segment attrs on local vars: 663 cananian 1.12 if (segment!=null && mode!=CODETABLE && !NO_SECTION_SUPPORT) 664 cananian 1.1.2.8 pwa[DI].print(" __attribute__ ((section (\"" + 665 cananian 1.1.2.8 sectionname(this.segment) +"\")))"); 666 cananian 1.13 // note that you will require -fno-zero-initialized-in-bss 667 cananian 1.13 // if building with NO_SECTION_SUPPORT, as gcc may change 668 cananian 1.13 // the section of any data struction without an explicit 669 cananian 1.13 // section attribute. (moves empty data structures to bss) 670 cananian 1.1.2.8 pwa[DI].println(" = {"); 671 cananian 1.1.2.1 } 672 cananian 1.1.2.1 public void visit(MEM e) { 673 cananian 1.1.2.1 Exp exp = e.getExp(); 674 cananian 1.1.2.1 pw.print("(*("); 675 cananian 1.1.2.1 pw.print("("+ctype(e)+"*)"); 676 cananian 1.1.2.1 trans(exp); 677 cananian 1.1.2.1 pw.print("))"); 678 cananian 1.1.2.1 } 679 cananian 1.1.2.2 private boolean isVoidMethod = false; 680 cananian 1.1.2.1 public void visit(METHOD e) { 681 cananian 1.1.2.5 this.method = e; 682 cananian 1.1.2.6 // have to discard the alignment (gcc won't let us specify it) 683 cananian 1.1.2.6 this.align = null; 684 cananian 1.1.2.6 // switch! 685 cananian 1.1.2.6 switchto(CODE); 686 cananian 1.1.2.7 // create common contents of declaration and definition 687 cananian 1.1.2.17 StringWriter protow = new StringWriter(); 688 cananian 1.1.2.17 pw = new PrintWriter(protow); 689 cananian 1.1.2.17 String prologue; 690 cananian 1.1.2.2 if (e.getReturnType() < 0) { 691 cananian 1.1.2.5 isVoidMethod = true; 692 cananian 1.1.2.17 prologue="FUNCV("; 693 cananian 1.1.2.5 } else { 694 cananian 1.1.2.5 isVoidMethod = false; 695 cananian 1.1.2.17 prologue="FUNC("+ctype(e.getReturnType())+", "; 696 cananian 1.1.2.5 } 697 cananian 1.1.2.17 // there's a space for the method name here. 698 cananian 1.1.2.17 pw.print(", ("); 699 cananian 1.1.2.5 for (int i=0; i<e.getParamsLength(); i++) { 700 cananian 1.1.2.5 if (i==0) pw.print("FIRST_DECL_ARG("); 701 cananian 1.1.2.1 pw.print(ctype(e.getParams(i))+" "); 702 cananian 1.1.2.3 temps_seen.add(e.getParams(i).temp);//suppress declaration 703 cananian 1.1.2.13 e.getParams(i).accept(this); 704 cananian 1.1.2.5 if (i==0) pw.print(") "); 705 cananian 1.1.2.5 else if (i+1 < e.getParamsLength()) pw.print(", "); 706 cananian 1.1.2.1 } 707 cananian 1.1.2.17 pw.print("), \""+sectionname(this.segment)+"\","); 708 cananian 1.1.2.7 pw.close(); 709 cananian 1.1.2.17 String declstr=prologue+label(e.getMethod())+protow.getBuffer(); 710 cananian 1.1.2.17 // declare this method. 711 cananian 1.1.2.17 sym2decl.put(e.getMethod(), "DECLARE"+declstr+");"); 712 cananian 1.1.2.17 // declare its aliases. 713 cananian 1.1.2.17 String aliasdeclstr=protow.getBuffer()+ 714 cananian 1.1.2.17 " __attribute__ ((alias (\""+label(e.getMethod())+"\"))));"; 715 cananian 1.22 for (Object aliasO : lv.method_labels) { 716 cananian 1.22 Label alias = (Label) aliasO; 717 cananian 1.1.2.17 sym2decl.put(alias, 718 cananian 1.1.2.17 "DECLARE"+prologue+label(alias)+aliasdeclstr); 719 cananian 1.1.2.17 } 720 cananian 1.1.2.17 // emit definition. 721 cananian 1.1.2.7 pw = pwa[MD]; 722 cananian 1.1.2.13 last_file=null; last_line=0; updateLine(e); 723 cananian 1.12 if (NO_SECTION_SUPPORT) 724 cananian 1.12 pw.println("#ifdef SECTION_" +sectionnameDEF(this.segment)); 725 cananian 1.1.2.17 pw.print("DEFINE"+declstr+")"); nl(); 726 cananian 1.1.2.5 pw.println("{"); 727 cananian 1.1.2.3 pw = pwa[MB]; 728 cananian 1.1.2.13 emitLineDirective(false); 729 cananian 1.1.2.1 } 730 cananian 1.1.2.1 public void visit(MOVE e) { 731 cananian 1.1.2.1 pw.print("\t"); 732 cananian 1.1.2.1 trans(e.getDst()); pw.print(" = "); trans(e.getSrc()); 733 cananian 1.7 pw.print(";"); nl(); 734 cananian 1.1.2.1 } 735 cananian 1.1.2.3 public void visit(NAME e) { visit(e, true); } 736 cananian 1.1.2.3 public void visit(NAME e, boolean take_address) { 737 cananian 1.1.2.3 /* add entry in symbol declaration table */ 738 cananian 1.1.2.14 if (!lv.local_code_labels.contains(e.label) && 739 cananian 1.1.2.14 !lv.local_table_labels.contains(e.label) && 740 cananian 1.1.2.14 !sym2decl.containsKey(e.label)) 741 cananian 1.1.2.7 sym2decl.put(e.label, "extern struct "+label(e.label)+" "+ 742 cananian 1.1.2.7 label(e.label)+";"); 743 cananian 1.1.2.14 if (take_address) { 744 cananian 1.1.2.14 pw.print("("); 745 cananian 1.1.2.31 pw.print("(void*)"); 746 cananian 1.1.2.14 pw.print("&"); 747 cananian 1.1.2.14 if (lv.local_code_labels.contains(e.label)) pw.print("&"); 748 cananian 1.1.2.14 } 749 cananian 1.1.2.3 pw.print(label(e.label)); 750 cananian 1.1.2.3 if (take_address) pw.print(")"); 751 cananian 1.1.2.1 } 752 cananian 1.1.2.1 public void visit(NATIVECALL e) { 753 cananian 1.1.2.20 // extract the name of the function to call, if known exactly. 754 cananian 1.1.2.20 String funcname = e.getFunc() instanceof NAME ? 755 cananian 1.1.2.20 ((NAME)e.getFunc()).label.name : null; 756 cananian 1.1.2.20 // this is a hack: calls to localref thunk functions aren't 757 cananian 1.1.2.20 // counted as gc points so that we don't screw up the localrefs 758 cananian 1.1.2.20 // stack in the middle of setting it up. 759 cananian 1.1.2.20 boolean nopush = "FNI_NewLocalRef".equals(funcname) || 760 cananian 1.1.2.20 "FNI_DeleteLocalRef".equals(funcname) || 761 kkz 1.1.2.33 "FNI_DeleteLocalRefsUpTo".equals(funcname) || 762 kkz 1.1.2.33 "generational_write_barrier".equals(funcname); 763 cananian 1.1.2.20 764 cananian 1.1.2.15 Set liveo = liveObjects(e); 765 cananian 1.1.2.20 if (!nopush) { // "special" functions known not to be gc-points. 766 cananian 1.7 pw.print("\t"); emitPush(liveo); pw.print(";"); nl(); 767 cananian 1.1.2.20 } 768 cananian 1.1.2.1 pw.print("\t"); 769 cananian 1.1.2.1 if (e.getRetval()!=null) { 770 cananian 1.1.2.1 trans(e.getRetval()); pw.print(" = "); 771 cananian 1.1.2.1 } 772 cananian 1.1.2.3 pw.print("("); 773 cananian 1.1.2.17 // hack to allow inlining calls to memset/etc. 774 cananian 1.1.2.14 if (e.getFunc() instanceof NAME && 775 cananian 1.16 (exactproto.contains(((NAME)e.getFunc()).label.name) || 776 cananian 1.16 ((NAME)e.getFunc()).label.name.startsWith("EXACT_"))) 777 cananian 1.1.2.17 pw.print(((NAME)e.getFunc()).label.name); 778 cananian 1.1.2.14 else { 779 cananian 1.1.2.1 /* function type cast */ 780 cananian 1.1.2.1 pw.print("("); 781 cananian 1.1.2.1 pw.print(e.getRetval()==null?"void":ctype(e.getRetval())); 782 cananian 1.1.2.1 pw.print("(*)("); 783 cananian 1.1.2.1 for (ExpList el=e.getArgs(); el!=null; el=el.tail) { 784 cananian 1.1.2.1 pw.print(ctype(el.head)); 785 cananian 1.1.2.1 if (el.tail!=null) pw.print(", "); 786 cananian 1.1.2.1 } 787 cananian 1.1.2.1 pw.print("))"); 788 cananian 1.1.2.1 /* function expression */ 789 cananian 1.1.2.1 trans(e.getFunc()); 790 cananian 1.1.2.14 } 791 cananian 1.1.2.3 pw.print(")("); 792 cananian 1.1.2.1 for (ExpList el=e.getArgs(); el!=null; el=el.tail) { 793 cananian 1.1.2.1 trans(el.head); 794 cananian 1.1.2.1 if (el.tail!=null) pw.print(", "); 795 cananian 1.1.2.1 } 796 cananian 1.7 pw.print(");"); nl(); 797 cananian 1.1.2.20 if (!nopush) { // "special" functions known not to be gc-points. 798 cananian 1.7 pw.print("\t"); emitPop(liveo); pw.print(";"); nl(); 799 cananian 1.1.2.20 } 800 cananian 1.1.2.1 } 801 cananian 1.1.2.1 public void visit(RETURN e) { 802 cananian 1.1.2.5 if (isVoidMethod) 803 cananian 1.7 pw.print("\tRETURNV();"); 804 cananian 1.1.2.4 else { 805 cananian 1.1.2.21 suppress_directives++; 806 cananian 1.1.2.5 pw.print("\tRETURN("+ctype(this.method.getReturnType())+","); 807 cananian 1.1.2.4 trans(e.getRetval()); 808 cananian 1.7 pw.print(");"); 809 cananian 1.1.2.21 suppress_directives--; 810 cananian 1.1.2.4 } 811 cananian 1.1.2.13 nl(); 812 cananian 1.1.2.1 } 813 cananian 1.1.2.1 public void visit(SEGMENT e) { 814 cananian 1.1.2.5 this.segment = e; 815 cananian 1.1.2.1 } 816 cananian 1.1.2.1 public void visit(SEQ e) { 817 cananian 1.1.2.1 trans(e.getLeft()); 818 cananian 1.1.2.1 trans(e.getRight()); 819 cananian 1.1.2.1 } 820 cananian 1.1.2.3 private Set temps_seen = new HashSet(); 821 cananian 1.1.2.1 public void visit(TEMP e) { 822 cananian 1.1.2.3 // declare the temp, if it hasn't already been seen. 823 cananian 1.1.2.3 if (!temps_seen.contains(e.temp)) { 824 cananian 1.1.2.3 temps_seen.add(e.temp); 825 cananian 1.7 pwa[MD].println("\tregister "+ctype(e)+" "+e.temp+";"); 826 cananian 1.1.2.3 } 827 cananian 1.1.2.1 pw.print(e.temp); 828 cananian 1.1.2.1 } 829 cananian 1.1.2.1 public void visit(THROW e) { 830 cananian 1.1.2.21 suppress_directives++; 831 cananian 1.1.2.4 if (isVoidMethod) { 832 cananian 1.7 pw.print("\tTHROWV("); trans(e.getRetex()); pw.print(");"); 833 cananian 1.1.2.4 } else { 834 cananian 1.1.2.5 pw.print("\tTHROW("+ctype(this.method.getReturnType())+", "); 835 cananian 1.1.2.4 trans(e.getRetex()); 836 cananian 1.7 pw.print(");"); 837 cananian 1.1.2.4 } 838 cananian 1.1.2.21 suppress_directives--; 839 cananian 1.1.2.13 nl(); 840 cananian 1.1.2.1 } 841 cananian 1.1.2.1 public void visit(UNOP e) { 842 cananian 1.1.2.1 pw.print("("); 843 cananian 1.1.2.1 switch(e.op) { 844 cananian 1.5 case Uop.NEG: pw.print("- "); break;//space after to prevent -- 845 cananian 1.1.2.1 case Uop.NOT: pw.print("~"); break; 846 cananian 1.1.2.22 case Uop.I2B: pw.print("(jbyte)"); break; 847 cananian 1.1.2.22 case Uop.I2C: pw.print("(jchar)"); break; 848 cananian 1.1.2.22 case Uop.I2S: pw.print("(jshort)"); break; 849 cananian 1.1.2.1 case Uop._2I: pw.print("(jint)"); break; 850 cananian 1.1.2.1 case Uop._2L: pw.print("(jlong)"); break; 851 cananian 1.1.2.1 case Uop._2F: pw.print("(jfloat)"); break; 852 cananian 1.1.2.1 case Uop._2D: pw.print("(jdouble)"); break; 853 cananian 1.1.2.1 default: throw new Error("unknown Uop: "+e); 854 cananian 1.1.2.1 } 855 cananian 1.1.2.1 trans(e.getOperand()); pw.print(")"); 856 cananian 1.1.2.15 } 857 cananian 1.1.2.15 858 cananian 1.1.2.15 Map temp2K = new HashMap(); 859 cananian 1.1.2.15 // emit an expression that saves the derivation of derived pointers. 860 cananian 1.1.2.15 private void emitHandleDerived(Set liveo, boolean isSave) { 861 cananian 1.22 for (Object tO : liveo) { 862 cananian 1.22 Temp t = (Temp) tO; 863 cananian 1.1.2.15 Derivation.DList dl=(Derivation.DList)tempv.objectTemps.get(t); 864 cananian 1.1.2.15 if (dl==null) continue; // not a derived temp. 865 cananian 1.1.2.15 // fetch name of temp in which to store derivation. 866 cananian 1.1.2.15 Temp K = (Temp) temp2K.get(t); 867 cananian 1.1.2.15 if (K==null) { // ooh, ooh, make new! 868 cananian 1.1.2.15 K = new Temp(t); 869 cananian 1.1.2.15 temp2K.put(t, K); 870 cananian 1.1.2.15 // declare the temp. 871 cananian 1.1.2.15 pwa[MD].println("\tregister jsize "+K+ 872 cananian 1.1.2.15 " __attribute__ ((unused));"); 873 cananian 1.1.2.15 } 874 cananian 1.1.2.15 if (isSave) pw.print(K+" = "+t); else pw.print(t+" = "+K); 875 cananian 1.1.2.15 while (dl!=null) { 876 cananian 1.1.2.15 pw.print((dl.sign^isSave)?"+":"-"); 877 cananian 1.1.2.29 pw.print("PTRMASK("+dl.base+")"); 878 cananian 1.1.2.15 dl=dl.next; 879 cananian 1.1.2.15 } 880 cananian 1.1.2.15 pw.print(","); 881 cananian 1.1.2.15 } 882 cananian 1.1.2.15 pw.print("0"); 883 cananian 1.1.2.15 } 884 cananian 1.1.2.15 // emit an expression to push object pointers and save derived types. 885 cananian 1.1.2.15 private void emitPush(Set liveo) { 886 cananian 1.1.2.15 pw.print("IFPRECISE(/*push*/("); 887 cananian 1.1.2.15 // push base pointers 888 cananian 1.22 for (Object tO : liveo) { 889 cananian 1.22 Temp t = (Temp) tO; 890 cananian 1.1.2.15 Derivation.DList dl=(Derivation.DList)tempv.objectTemps.get(t); 891 cananian 1.1.2.15 if (dl!=null) continue; // only base pointers! 892 cananian 1.1.2.15 pw.print("PUSHOBJ("+t+"),"); 893 cananian 1.1.2.15 } 894 cananian 1.1.2.15 // handle derived pointers. 895 cananian 1.1.2.15 emitHandleDerived(liveo, true/* save */); 896 cananian 1.1.2.15 pw.print("))"); 897 cananian 1.1.2.15 } 898 cananian 1.1.2.15 // emit an expression to pop object pointers and restore derived types 899 cananian 1.1.2.15 private void emitPop(Set liveo) { 900 cananian 1.1.2.15 pw.print("IFPRECISE(/*pop */("); 901 cananian 1.1.2.15 // pop base pointers 902 cananian 1.1.2.18 for (Iterator it=new ReverseIterator(liveo.iterator()); 903 cananian 1.1.2.18 it.hasNext(); ) { 904 cananian 1.1.2.15 Temp t = (Temp) it.next(); 905 cananian 1.1.2.15 Derivation.DList dl = 906 cananian 1.1.2.15 (Derivation.DList) tempv.objectTemps.get(t); 907 cananian 1.1.2.15 if (dl!=null) continue; // only base pointers! 908 cananian 1.1.2.15 pw.print(t+"=POPOBJ(),"); 909 cananian 1.1.2.15 } 910 cananian 1.1.2.15 // handle derived pointers. 911 cananian 1.1.2.15 emitHandleDerived(liveo, false/* restore */); 912 cananian 1.1.2.15 pw.print("))"); 913 cananian 1.1.2.15 } 914 cananian 1.1.2.15 // return the set of objects to be saved/restored at a given alloc site 915 cananian 1.1.2.15 private Set liveObjects(INVOCATION e) { 916 cananian 1.1.2.15 if (live==null || tempv==null || ud==null) 917 cananian 1.1.2.15 return Collections.EMPTY_SET; // bail out if no liveness info. 918 cananian 1.1.2.15 // SAVE: (liveOut(e)-e.defs()) intersected w/ objectTemps 919 cananian 1.9 Set lo = new TreeSet();//HashSet(); 920 cananian 1.22 for (Object tO : live.getLiveOut(e)) { 921 cananian 1.22 Temp t = (Temp) tO; 922 cananian 1.1.2.15 // filter out non-object temps. 923 cananian 1.1.2.15 if (!tempv.objectTemps.containsKey(t)) continue; 924 cananian 1.1.2.15 lo.add(t); 925 cananian 1.1.2.15 // derived temps are also uses of their bases. 926 cananian 1.1.2.15 Derivation.DList dl=(Derivation.DList)tempv.objectTemps.get(t); 927 cananian 1.1.2.15 while (dl!=null) { 928 cananian 1.1.2.15 lo.add(dl.base); 929 cananian 1.1.2.15 dl=dl.next; 930 cananian 1.1.2.15 } 931 cananian 1.1.2.15 } 932 cananian 1.1.2.15 // filter out temps def'ed by INVOCATION 933 cananian 1.1.2.15 lo.removeAll(ud.defC(e)); 934 cananian 1.1.2.15 // done. 935 cananian 1.1.2.15 return lo; 936 cananian 1.1.2.1 } 937 cananian 1.1.2.1 } 938 cananian 1.2 }