-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTMUtils.java
More file actions
388 lines (330 loc) · 12 KB
/
Copy pathTMUtils.java
File metadata and controls
388 lines (330 loc) · 12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
import absyn.*;
import java.lang.String;
import java.util.*;
import java.io.*;
/* TM Utils
* General goal of this class is to abstract the tree traversal and high level generation
* from the direct C instruction to TM instruction conversion
* TODO add utility function to help aid in conversion
*/
public class TMUtils
{
PrintWriter printer = null;
//Constant definitions
final static int SPACES = 4;
//Special registers
final static int pc = 7;
final static int gp = 6;
final static int fp = 5;
final static int ac = 0;
final static int ac1 = 1;
//Constants
final static int GLOBAL_SCOPE = 0;
private static int ins = 0;
private static int mainLoc = 0;
//Next available loc after global frame, basically record memory space used by global var
private static int globalOffset = 0;
private static int currentFrameOffset = 0;
public TMUtils(String fileName) {
try {
printer = new PrintWriter(fileName.split("\\.")[0]+".tm", "utf-8");
} catch (Exception e) {
System.out.println(e);
}
}
public int getCurrINS() {
return ins;
}
//Utility functions, can change where the output is directed here
public void emitComment(String line) {
printer.println("* "+line);
}
public void emit(String line) {
printer.println(ins++ + ": "+line);
}
public void emit(int ins, String line) {
printer.println(ins + ": "+line);
}
//#region[rgba(150, 10, 10, 0.15)] All instructions are either R0 or RM instructions
//Slide 3 from TMSim slides
public void emitR0Instruction(String opCode, int r, int s, int t, String comment) {
emit(opCode+" "+r+","+s+","+t+"\t"+comment);
}
//Slide 4 from TMSim slides
public void emitRMInstruction(String opCode, int r, int d, int s, String comment) {
emit(opCode+" "+r+","+d+"("+s+")\t"+comment);
}
//#endregion
//#region[rgba(10,40,120,0.3)] Helper functions
//Output a comment and skip a line, return skipped position
public int emitSkip(String msg) {
emitComment(msg);
return ins++;
}
public void emitJump(String opCode, int r, int startLoc, int endLoc, String msg) {
int offset = endLoc - startLoc - 1;
//Set PC Reg to PC REG + offset
emit(startLoc, opCode+" "+r+","+offset+"("+pc+")"+"\t"+msg);
if (startLoc==ins)
ins++;
}
public void emitJump(int startLoc, int endLoc, String msg) {
emitJump("LDA", pc, startLoc, endLoc, msg);
}
public void emitJumpToCurrentINS(int startLoc, String msg) {
emitJump(startLoc, ins, msg);
}
public void emitJumpToCurrentINS(String opCode, int r, int startLoc, String msg) {
emitJump(opCode, r, startLoc, ins, msg);
}
public int newTemp() {
int tmp = currentFrameOffset;
currentFrameOffset -= 1;
emitRMInstruction("ST", ac, tmp, fp, "op: push tmp left");
return tmp;
}
public void releaseTempVar() {
currentFrameOffset++;
}
//#endregion
//#region[rgba(90,10,90, 0.1)] High level instruction utils
public int buildFunction(FunctionDec dec, String name) {
int loc = emitSkip("Function: "+name);
emitRMInstruction("ST", ac, -1, fp, "store return");
if (name.equals("main"))
mainLoc = loc;
dec.address = loc;
//position 0 is ofp
//position -1 is ret-addr
currentFrameOffset = -2;
return loc;
}
public void finishFunction(int loc, String name) {
emitRMInstruction("LD", pc, -1, fp, "return to caller");
emitJump(loc, ins, "Jump around function: "+name);
emitComment("End function: "+name);
}
public void processSimpleDec(SimpleDec var, int depth) {
if (depth == GLOBAL_SCOPE) {
emitComment("Processing global var declaration: "+var.name);
var.offset = globalOffset;
globalOffset--;
var.nestLevel = 0;
} else {
emitComment("Processing local var declaration: "+var.name);
var.offset = currentFrameOffset;
currentFrameOffset--;
var.nestLevel = 1;
}
}
public void processArrayDec(ArrayDec var, int size, int depth) {
if (depth == GLOBAL_SCOPE) {
emitComment("Processing global var[] declaration: "+var.name);
var.offset = globalOffset;
globalOffset-=size;
var.nestLevel = 0;
} else {
emitComment("Processing local var[] declaration: "+var.name);
var.offset = currentFrameOffset;
currentFrameOffset-=size;
var.nestLevel = 1;
}
}
public void verifyArrayAccess(int maxSize) {
emitRMInstruction("JLT", ac, 1, pc, "Halt if subscript < 0");
emitRMInstruction("LDA", pc, 1, pc, "Jump over if not");
emitR0Instruction("HALT", 0, 0, 0, "End (rip)");
//TODO check max size
//TODO output error
}
public void loadArray(IndexVar var, TMDecEntry dec, boolean assign, int tmpVar) {
//sub offset of base addr
//load value using addr stored
emitRMInstruction("LD", ac1, tmpVar, fp, "load array base addr");
emitR0Instruction("SUB", ac, ac1, ac, "base is at top of array");
if(!assign)
emitRMInstruction("LD", ac, 0, ac, "load value at array index");
//pop tmp var and other shit off the stack
currentFrameOffset = tmpVar;
}
public void loadVar(Var var, TMDecEntry dec, boolean isAddr) {
if (!(dec.dec instanceof VarDec)) {
emitComment("Error loading simple var: looking for VarDec, got function dec");
return;
}
VarDec varDec = (VarDec)dec.dec;
//TODO we need logic in order to determine if we use LD or LDA, GG, kinda working now
String op = "LD";
if (isAddr)
op = "LDA";
//Global
emitComment("Looking up: "+var.name);
if (varDec.nestLevel == 0) {
emitRMInstruction(op, ac, varDec.offset, gp, "load id");
}
else //Local
{
emitRMInstruction(op, ac, varDec.offset, fp, "load id");
}
}
public int startCallExp() {
int frameStart = currentFrameOffset;
currentFrameOffset-=2;
return frameStart;
}
public int processCallExp(CallExp e, FunctionDec func, int depth, int frameStart) {
emitComment("-> call of function: " + e.func);
//int frameStart = currentFrameOffset;
//currentFrameOffset -= 2;
//args handled by pushArgOnStack()
if(func != null) {
emitRMInstruction("ST", fp, frameStart, fp, "push ofp");
emitRMInstruction("LDA", fp, frameStart, fp, "push frame");
emitRMInstruction("LDA", ac, 1, pc, "load ac with ret ptr");
emitJump(ins, func.address, "Jump to function location");
emitRMInstruction("LD", fp, 0, fp, "pop frame");
}
else
{
//report_error(exp.row, exp.col, "function: " + exp.func + " not found");
}
//TODO figure out how tf to handle this
currentFrameOffset = frameStart;
emitComment("<- call");
return frameStart;
}
public void finishCallExp(int frameStart) {
currentFrameOffset = frameStart;
}
public void pushArgOnStack(int size) {
emitRMInstruction("ST", ac, currentFrameOffset, fp, "store arg val");
currentFrameOffset--;
}
public void returnToCaller() {
emitRMInstruction("LD", pc, -1, fp, "return to caller");
}
public void processConstant(IntExp e) {
emitComment("-> cosntant: "+e.value);
emitRMInstruction("LDC", ac, e.value, ac, "load constant");
emitComment("<- constant");
}
public void processResultAssignExp(int tmpOffset) {
emitRMInstruction("LD", ac1, tmpOffset, fp, "op: load left");
emitRMInstruction("ST", ac, 0, ac1, "assign: store value");
}
//Builds and operator expressions and puts the result in a tmp var located in the offset
public void processResultTmpOpExp(OpExp e, int tmpOffset) {
emitRMInstruction("LD", ac1, tmpOffset, fp, "op: load left");
emitR0Instruction(getTMExpCode(e.op), ac, ac1, ac, "op " + getOpString(e.op));
}
public int processIfJump(OpExp e) {
if (getTMOpCode(e.op).charAt(0)=='J')
emitRMInstruction(getTMOpCode(e.op), ac, 2, pc, "br if true");
else
emitR0Instruction(getTMOpCode(e.op), ac, 2, pc, "br if true");
emitRMInstruction("LDC", ac, 0, 0, "false case");
emitRMInstruction("LDA", pc, 1, pc, "unconditional jump");
emitRMInstruction("LDC", ac, 1, 0, "true case");
int jmpLoc = emitSkip("If jump location");
return jmpLoc;
}
//#endregion
public void prelude(String fileName) {
emitComment("C-Minus Compilation to TM Code");
emitComment("File: "+fileName);
emitComment("Standard prelude:");
emitRMInstruction("LD", gp, 0, ac,"load gp with maxaddress");
emitRMInstruction("LDA", fp, 0, gp,"copy to gp to fp");
emitRMInstruction("ST", 0, 0, ac,"clear location 0");
emitComment("Jump around i/o routines here");
int loc = emitSkip("Function input");
emitRMInstruction("ST", ac, -1, fp, "store return");
emitR0Instruction("IN", 0, 0, 0, "Input");
emitRMInstruction("LD", pc, -1, fp, "Return to caller");
emitComment("code for output routine");
emitRMInstruction("ST", ac, -1, fp, "store return");
emitRMInstruction("LD", ac, -2, fp, "load emitput value");
emitR0Instruction("OUT", 0, 0, 0, "output");
emitRMInstruction("LD", pc, -1, fp, "return to caller");
emitJump(loc, ins, "Jump around I/O code");
emitComment("End of standard prelude.");
}
public void end() {
//Will need to get the global offset
emitRMInstruction("ST", fp, globalOffset, fp, "push ofp");
emitRMInstruction("LDA", fp, globalOffset, fp, "push frame");
emitRMInstruction("LDA", ac, 1, pc, "load ac with ret ptr");
emitRMInstruction("LDA", pc, -(ins-mainLoc), pc, "jump to main location");
emitRMInstruction("LD", fp, 0, fp, "pop frame");
emitR0Instruction("HALT", 0, 0, 0, "End");
printer.close();
}
public String getTMOpCode(int op) {
switch(op) {
case OpExp.PLUS:
return "ADD";
case OpExp.MINUS:
return "SUB";
case OpExp.MUL:
return "MUL";
case OpExp.DIV:
return "DIV";
case OpExp.EQ:
return "JEQ";
case OpExp.NE:
return "JNE";
case OpExp.LT:
return "JLT";
case OpExp.LE:
return "JLE";
case OpExp.GT:
return "JGT";
case OpExp.GE:
return "JGE";
default:
return "Error getting operator asm code";
}
}
//If the code is a boolean expression well do a subtraction in prep for a jump
public String getTMExpCode(int op) {
switch(op)
{
case OpExp.PLUS:
return "ADD";
case OpExp.MINUS:
return "SUB";
case OpExp.MUL:
return "MUL";
case OpExp.DIV:
return "DIV";
default:
return "SUB";
}
}
public String getOpString(int op) {
switch(op) {
case OpExp.PLUS:
return "+";
case OpExp.MINUS:
return "-";
case OpExp.MUL:
return "*";
case OpExp.DIV:
return "/";
case OpExp.EQ:
return "==";
case OpExp.NE:
return "!=";
case OpExp.LT:
return "<";
case OpExp.LE:
return "<=";
case OpExp.GT:
return ">";
case OpExp.GE:
return ">=";
default:
return "??? error with operator code: "+op;
}
}
}