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      }