1
3 package jminusminus;
4
5 import static jminusminus.CLConstants.*;
6 import java.io.BufferedReader;
7 import java.io.FileReader;
8 import java.io.File;
9 import java.io.FileNotFoundException;
10 import java.io.IOException;
11 import java.io.PrintWriter;
12 import java.util.ArrayList;
13 import java.util.Calendar;
14 import java.util.HashMap;
15
16
19
20 public class NEmitter {
21
22
23 private String sourceFile;
24
25
29 private HashMap<CLFile, HashMap<CLMethodInfo, NControlFlowGraph>> classes;
30
31
32 private String destDir;
33
34
37 private boolean errorHasOccurred;
38
39
48
49 private void reportEmitterError(String message, Object... args) {
50 System.err.printf(message, args);
51 System.err.println();
52 errorHasOccurred = true;
53 }
54
55
67
68 private void pushStackFrame(NControlFlowGraph cfg, PrintWriter out) {
69 int frameSize = cfg.pRegisters.size() * 4 + cfg.offset * 4 + 8;
70 out.printf(
71 " subu $sp,$sp,%d \t # Stack frame is %d bytes long\n",
72 frameSize, frameSize);
73 out.printf(" sw $ra,%d($sp) \t # Save return address\n",
74 frameSize - 4);
75 out.printf(" sw $fp,%d($sp) \t # Save frame pointer\n",
76 frameSize - 8);
77 int i = 12;
78 for (NPhysicalRegister pRegister : cfg.pRegisters) {
79 out.printf(" sw %s,%d($sp) \t # Save register %s\n",
80 pRegister, frameSize - i, pRegister);
81 i += 4;
82 }
83 out.printf(" addiu $fp,$sp,%d \t # Save frame pointer\n",
84 frameSize - 4);
85 out.println();
86 }
87
88
100
101 private void popStackFrame(NControlFlowGraph cfg, PrintWriter out) {
102 int frameSize = cfg.pRegisters.size() * 4 + cfg.offset * 4 + 8;
103 out.printf("%s.restore:\n", cfg.labelPrefix);
104 out.printf(" lw $ra,%d($sp) \t # Restore return address\n",
105 frameSize - 4);
106 out.printf(" lw $fp,%d($sp) \t # Restore frame pointer\n",
107 frameSize - 8);
108 int i = 12;
109 for (NPhysicalRegister pRegister : cfg.pRegisters) {
110 out.printf(" lw %s,%d($sp) \t # Restore register %s\n",
111 pRegister, frameSize - i, pRegister);
112 i += 4;
113 }
114 out.printf(" addiu $sp,$sp,%d \t # Pop stack\n", frameSize);
115 out.printf(" jr $ra \t # Return to caller\n", frameSize);
116 out.println();
117 }
118
119
129
130 public NEmitter(String sourceFile, ArrayList<CLFile> clFiles, String ra) {
131 this.sourceFile = sourceFile.substring(sourceFile
132 .lastIndexOf(File.separator) + 1);
133 classes = new HashMap<CLFile, HashMap<CLMethodInfo, NControlFlowGraph>>();
134 for (CLFile clFile : clFiles) {
135 CLConstantPool cp = clFile.constantPool;
136 HashMap<CLMethodInfo, NControlFlowGraph> methods = new HashMap<CLMethodInfo, NControlFlowGraph>();
137 for (int i = 0; i < clFile.methodsCount; i++) {
138 CLMethodInfo m = clFile.methods.get(i);
139
140 NControlFlowGraph cfg = new NControlFlowGraph(cp, m);
145
146 PrettyPrinter p = new PrettyPrinter();
148 p.printf("%s %s\n", cfg.name, cfg.desc);
149 cfg.writeTuplesToStdOut(p);
150
151 cfg.detectLoops(cfg.basicBlocks.get(0), null);
155
156 cfg.removeUnreachableBlocks();
158
159 cfg.computeDominators(cfg.basicBlocks.get(0), null);
161
162 cfg.tuplesToHir();
165
166 cfg.eliminateRedundantPhiFunctions();
170
171 cfg.optimize();
174
175 cfg.writeHirToStdOut(p);
177
178 cfg.hirToLir();
181
182 cfg.resolvePhiFunctions();
184
185 cfg.orderBlocks();
187
188 cfg.renumberLirInstructions();
190
191 cfg.writeLirToStdOut(p);
193
194 methods.put(m, cfg);
197
198 NRegisterAllocator regAllocator;
200 if (ra.equals("naive")) {
201 regAllocator = new NNaiveRegisterAllocator(cfg);
202 } else if (ra.equals("linear")) {
203 regAllocator = new NLinearRegisterAllocator(cfg);
204 } else {
205 regAllocator = new NGraphRegisterAllocator(cfg);
206 }
207 regAllocator.allocation();
208
209 cfg.writeIntervalsToStdOut(p);
211
212 cfg.allocatePhysicalRegisters();
215
216 cfg.writeLirToStdOut(p);
218 }
219
220 classes.put(clFile, methods);
222 }
223 }
224
225
231
232 public void destinationDir(String destDir) {
233 this.destDir = destDir;
234 }
235
236
241
242 public boolean errorHasOccurred() {
243 return errorHasOccurred;
244 }
245
246
250
251 public void write() {
252 String file = "";
253 try {
254 file = destDir + File.separator + sourceFile.replace(".java", ".s");
255 PrintWriter out = new PrintWriter(file);
256
257 out.printf("# %s\n", file);
259 out.printf("# Source file: %s\n", sourceFile);
260 out.printf("# Compiled: %s\n\n", Calendar.getInstance().getTime()
261 .toString());
262
263 for (CLFile clFile : classes.keySet()) {
265 HashMap<CLMethodInfo, NControlFlowGraph> aClass = classes
266 .get(clFile);
267 CLConstantPool cp = clFile.constantPool;
268 int nameIndex = ((CLConstantClassInfo) cp
269 .cpItem(clFile.thisClass)).nameIndex;
270 String className = new String(((CLConstantUtf8Info) cp
271 .cpItem(nameIndex)).b);
272 for (CLMethodInfo m : aClass.keySet()) {
273 NControlFlowGraph cfg = aClass.get(m);
274 String methodName = cfg.name;
275 String methodDesc = cfg.desc;
276 if (methodName.equals("<init>")) {
277 continue;
278 }
279 out.printf(".text\n\n");
280 if (methodName.equals("main")
281 && methodDesc.equals("([Ljava/lang/String;)V")) {
282 out.printf("%s:\n", methodName);
283 cfg.labelPrefix = methodName;
284 } else {
285 out.printf("%s.%s:\n", className, methodName);
286 cfg.labelPrefix = className + "." + methodName;
287 }
288
289 pushStackFrame(cfg, out);
291
292 for (NBasicBlock block : cfg.basicBlocks) {
293 out.printf("%s.%d:\n", cfg.labelPrefix, block.id);
294 for (NLIRInstruction lir : block.lir) {
295 lir.toSpim(out);
296 }
297 out.printf("\n");
298 }
299
300 popStackFrame(cfg, out);
302
303 if (cfg.data.size() > 0) {
306 out.printf(".data\n\n");
307 for (String line : cfg.data) {
308 out.printf(line);
309 }
310 }
311
312 out.printf("\n\n");
313 }
314 }
315
316 String[] libs = { "SPIM.s" };
318 out.printf("# SPIM Runtime\n\n");
319 for (String lib : libs) {
320 file = System.getenv("j") + File.separator + "src"
321 + File.separator + "spim" + File.separator + lib;
322 BufferedReader in = new BufferedReader(new FileReader(file));
323 String line;
324 while ((line = in.readLine()) != null) {
325 out.printf("%s\n", line);
326 }
327 in.close();
328 }
329
330 out.close();
331 } catch (FileNotFoundException e) {
332 reportEmitterError("File %s not found", file);
333 } catch (IOException e) {
334 reportEmitterError("Cannot write to file %s", file);
335 }
336 }
337
338 }
339