-
Notifications
You must be signed in to change notification settings - Fork 0
/
GenCode.java
482 lines (407 loc) · 14.4 KB
/
GenCode.java
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
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
import java.util.HashMap;
import java.util.ArrayList;
import java.util.*;
import absyn.*;
public class GenCode {
private static final int PC = 7;
private static final int GP = 6;
private static final int FP = 5;
private static final int RR = 0; //result register
private static final int AC1 = 1;
private static final int TR = 4; //temp register
private static String code = "";
private static int currLine = 11;
private static HashMap<String, Frame> frames = new HashMap<>();
GenCode( ExpList tree )
{
//make standard prelude
code += "*input Function\n";
currLine = 1;
outputLine("IN",RR,0,0);
outputLine("LD", TR, 0, FP);
outputLine("LDA", PC, 1, TR, "*return to caller");
code += "*end input function\n";
code += "*output Function\n";
outputLine("LD", 0, -1, FP);
outputLine("OUT",0,0,0);
outputLine("LD", TR, 0, FP);
outputLine("LDA", PC, 1, TR, "*return to caller");
code += "*end output Function\n";
// add default functions
Frame temp = new Frame(new FunDec(-1, "int", "input", null, null), 1);
frames.put("input", temp);
System.out.println("input");
temp.printFrame();
temp = new Frame(new FunDec(-1, "void", "output", new ExpList(new VarDec(-1, "int", "x"), null), null), 4);
frames.put("output", temp);
temp.addParam(new VarDec(-1, "int", "x"));
System.out.println("output");
temp.printFrame();
//generate the functions
GenCode(tree, null); //NOTE: no globals YET
//jump functions
code += "0: LDC " + PC + "," + currLine + "(0) jump around functions\n";
//creat first stack frame for main
Frame mainFrame = frames.get("main");
if (mainFrame != null)
{ //this 4 is how many more lines to skip to get past this caller
outputLine("LDA", FP, mainFrame.params, FP, "initial FP for main");
outputLine("ST", PC, 0, FP, "Store return for main caller");
outputLine("LDC", PC, mainFrame.codeStart,0, "move PC to main");
}
//halt line
code += currLine + ": HALT 0,0,0\n";
currLine++;
}
static public String returnAssembly()
{
return code;
}
static public void GenCode( ExpList tree, Frame f ) {
while( tree != null ){
if (f != null)
f.resetStack();
GenCode( tree.head, f);
tree = tree.tail;
}
}
static private void outputLine(String command, int r, int d, int s, String comment)
{
switch(command)
{
case "IN":
case "OUT":
case "HALT":
case "ADD":
case "SUB":
case "MUL":
case "DIV":
code += currLine + ": " + command + " " + r + "," + d + "," + s + " " + comment + "\n";
break;
default:
code += currLine + ": " + command + " " + r + "," + d + "(" + s + ") " + comment + "\n";
break;
}
currLine++;
}
static private void outputLine(String command, int r, int d, int s)
{
switch(command)
{
case "IN":
case "OUT":
case "HALT":
case "ADD":
case "SUB":
case "MUL":
case "DIV":
code += currLine + ": " + command + " " + r + "," + d + "," + s + "\n";
break;
default:
code += currLine + ": " + command + " " + r + "," + d + "(" + s + ")\n";
break;
}
currLine++;
}
static private void GenCode( FunDec tree)
{
code += "*start assembling function " + tree.name + "\n";
//LOAD FRAME
Frame f = new Frame(tree, currLine); //create frame for this function
frames.put(tree.name, f); //store frame info globaly
//add parameters to frame
ExpList varList = tree.paramList;
while( varList != null ){
f.addParam(varList.head);
varList = varList.tail;
}
//get body contents
ComStmt body = (ComStmt)(tree.comStmt);
//add locals to frame
varList = body.locals;
while( varList != null ){
f.addLocal(varList.head);
varList = varList.tail;
}
//temp, print frame contents
System.out.println("*FRAME VVV " + tree.name);
f.printFrame();
System.out.println("*FRAME ^^^");
//At this point control has been assumed
GenCode(body.statements, f);
//Give back control
outputLine("LD", TR, 0, FP);
outputLine("LDA", PC, 1, TR, "*return to caller " + tree.name + "<<<<<");
code += "*stop assembling function " + tree.name + "\n";
}
static private void GenCode( FunCall tree, Frame f)
{
//push arguments onto the stack
System.out.println("\n-funcall " + tree.name + " " + tree.pos);
ExpList args = tree.argList;
code += "*Start loading parameters for call to " + tree.name + "\n";
while( args != null)
{
GenCode(args.head, f); //expect value to be left at current stack height
code += "*current stack " + f.getStackOffset() + "\n";
if (args.head instanceof FunCall)
outputLine("ST", RR, f.getStackOffset() ,FP, "Getting the return out of r0 and putting it on the stack");
args = args.tail;
}
//get next function frame
Frame nextFrame = frames.get(tree.name);
int frameOffSet = f.getFrameOffset(nextFrame);
System.out.println("___\nnext frame " + tree.name);
System.out.println("next params " + nextFrame.params);
System.out.println("current locals " + f.locals);
System.out.println("current stack " + f.getStackOffset());
System.out.println("offset to next frame " + frameOffSet);
code += "*Calling function\n";
//set the new FP
outputLine("LDA", FP, frameOffSet, FP, "Start call to " + tree.name + " line: " + tree.pos);
//store the PC to come back to at the new FP
outputLine("ST", PC, 0, FP, "Moving return PC to func being called");
//move PC to the function being called
outputLine("LDC", PC, nextFrame.codeStart, 0);
//move FP back
outputLine("LDA", FP, -frameOffSet, FP, "End call to "+ tree.name + " line: " + tree.pos);
//if this function returns something, we must get it from RR and put it onto the stack
if (nextFrame.function.type != "void")
{
f.decrementStack(nextFrame.params - 1);
outputLine("ST", RR, f.getStackOffset(), FP, "Putting return onto the stack");
}
code += "*Done func call to " + tree.name + "\n";
}
static private int GenCode( IntVal tree, Frame f)
{
f.incrementStack();
//put an integer into r0
outputLine("LDC", RR, tree.val, 0);
//put that integer onto the stackPointer
outputLine("ST", RR, f.getStackOffset(), FP, "int " + tree.val + " pushed to stack");
return tree.val;
}
static private void GenCode( VarExp tree, Frame f)
{
f.incrementStack();
//put an the value into r0
outputLine("LD", RR, f.getVarOffset(tree), FP);
//put that value onto the stackPointer
outputLine("ST", RR, f.getStackOffset(), FP, "variable " + tree.name + " pushed to stack");
}
static private void GenCode( RetExp tree, Frame f)
{
//leave answer in stackq
GenCode(tree.toRet, f);
//put answer in previous stack
code += "*current stack at return " + f.getStackOffset() + "\n";
outputLine("LD", RR, f.getStackOffset(), FP, "Moving value to previous stack frame stack");
}
static private void GenCode( AssignExp tree, Frame f)
{
//stack does not get bigger because the assignment leaves one variable on the stack and the stack already gets incremented by the following GenCode
//get the right hand side onto the stack
code += "*" + f.getStackOffset() + "\n";
GenCode(tree.rhs, f);
//assign the top of the stack to lhs, leave it on top of the stack
outputLine("LD", RR, f.getStackOffset(), FP, "loading the top of the stack to r0 stack="+f.getStackOffset());
outputLine("ST", RR, f.getVarOffset(tree.lhs), FP, "assigning it");
}
/* static private void valueMightBeAFunc( Exp call, Frame f)
{
//Since functions return to RR and do not leave anything on the stack it is
//important to make sure that if we need to get 2 things on a stack, that we
//do it manually if the lhs or rhs is a functions
//more of bandage fix than anything, surely there's a better way to reformat
//the programs stucture so that this function need not exist
GenCode(call, f);
if (call instanceof FunCall)
{
//manually push to stack
f.incrementStack();
outputLine("ST", RR, f.getStackOffset(), FP, "VMBAF Putting return onto the stack");
}
}*/
static private void GenCode( BinOp tree, Frame f)
{
//get the left and the right side things pushed onto the stack
GenCode(tree.left, f);
GenCode(tree.right, f);
outputLine("LD", 2, f.getStackOffset(), FP, "Load left and right hand side from stack");
f.decrementStack();
outputLine("LD", 1, f.getStackOffset(), FP);
switch(tree.op)
{
case 0:
outputLine("ADD", 0,1,2);
break;
case 1:
outputLine("SUB", 0,1,2);
break;
case 2:
outputLine("MUL", 0,1,2);
break;
case 3:
outputLine("DIV", 0,1,2);
break;
}
outputLine("ST", 0, f.getStackOffset(), FP, "Store result back onto stack");
}
static private void GenCode( ComStmt tree, Frame f)
{
f.addScope();
//make a new scope
ExpList locals = tree.locals;
while( locals != null)
{
f.addLocal(locals.head);
locals = locals.tail;
}
//generate the inside code
GenCode(tree.statements, f);
//remove the scope
f.popScope();
}
static private void GenCode( RelOp tree, Frame f )
{
GenCode(tree.left, f);
GenCode(tree.right, f);
//NOTE: LEFT SIDE MINUS RIGHT SIDE
//similar to binary operators
outputLine("LD", 2, f.getStackOffset(), FP, "Load left and right hand side from stack");
f.decrementStack();
outputLine("LD", 1, f.getStackOffset(), FP);
outputLine("SUB", RR,1,2, "Sub r1 from r2, store in r0. Used for comparison");
switch (tree.op)
{
case RelOp.LT:
outputLine("JLT", RR, 2, PC);
break;
case RelOp.LE:
outputLine("JLE", RR, 2, PC);
break;
case RelOp.EQ:
outputLine("JEQ", RR, 2, PC);
break;
case RelOp.GE:
outputLine("JGE", RR, 2, PC);
break;
case RelOp.GT:
outputLine("JGT", RR, 2, PC);
break;
case RelOp.NE:
outputLine("JNE", RR, 2, PC);
break;
}
outputLine("LDC", RR, 0, 0, "comparison was false");
outputLine("LDA", PC, 1, PC);
outputLine("LDC", RR, 1, 0, "comparison was true");
outputLine("ST", RR, f.getStackOffset(), FP, "Store result back onto stack");
}
static private void GenCode( WhileExp tree, Frame f)
{
code += "*Start while\n";
//store where the test starts
int testStart = currLine;
//puts the result of the test on the stack
GenCode(tree.test, f);
//save a spot for the jump
int whileJump = currLine++;
GenCode(tree.statements, f);
outputLine("LDA", PC, -(currLine - testStart + 1), PC, "Jump back to while");
//put in the jump
code += whileJump + ": JEQ " + RR + "," + (currLine - whileJump - 1) + "(" + PC + ") while jump\n";
code += "*End while\n";
}
static private void GenCode( IfExp tree, Frame f )
{
code += "*begin if statement\n";
//this puts the answer in the top of the stack
GenCode(tree.test, f);
int ifJump = currLine++;
GenCode(tree.thenpart, f);
if (tree.elsepart != null)
{
int elseJump = currLine++;
GenCode(tree.elsepart, f);
code += elseJump + ": LDA " + PC + "," + (currLine - elseJump - 1) + "(" + PC + ") skip else\n";
code += ifJump + ": JEQ " + RR + "," + (elseJump - ifJump) + "(" + PC + ") conditional jump\n";
}
else
{ //no else statement
code += ifJump + ": JEQ " + RR + "," + (currLine - ifJump - 1) + "(" + PC + ") conditional jump\n";
}
code += "*end if statement\n";
}
static private String GenCode( Exp tree, Frame f ) {
if( tree instanceof FunDec )
GenCode( (FunDec)tree );
else if( tree instanceof FunCall )
GenCode( (FunCall)tree, f);
else if( tree instanceof VarDec )
GenCode( (VarDec)tree, f );
else if( tree instanceof RetExp )
GenCode( (RetExp)tree, f );
else if( tree instanceof IntVal )
GenCode( (IntVal)tree, f );
else if( tree instanceof VarExp )
GenCode( (VarExp)tree, f );
else if( tree instanceof AssignExp )
GenCode( (AssignExp)tree, f );
else if( tree instanceof BinOp )
GenCode( (BinOp)tree, f );
else if( tree instanceof ComStmt )
GenCode( (ComStmt)tree, f );
else if( tree instanceof IfExp )
GenCode( (IfExp)tree, f );
else if( tree instanceof RelOp )
GenCode( (RelOp)tree, f );
else if( tree instanceof WhileExp )
GenCode( (WhileExp)tree, f );
/*else if( tree instanceof ArrExp )
return GenCode( (ArrExp)tree, curScope );
else if( tree instanceof ArrDec )
GenCode( (ArrDec)tree, curScope);*/
else
System.out.println( "You didn't define this you dingus: " + tree.toString() +tree.pos );
return null;
}
/*
static private void GenCode( ArrDec tree, HashMap curScope)
{
Object inMap = curScope.get(tree.name);
if (inMap != null)
System.out.println("Error line " + tree.pos + ": Variable \"" + tree.name + "\" already defined at line " + ((ArrDec)inMap).pos);
else
{
inMap = functions.get(tree.name);
if (inMap != null)
{
if (((FunDec)inMap).pos == -1)
System.out.println("Error line " + tree.pos + ": Variable \"" + tree.name + "\" trying to redefine built in");
else
System.out.println("Error line " + tree.pos + ": Variable \"" + tree.name + "\" already defined at line " + ((ArrDec)inMap).pos + " as a function");
}
else
curScope.put(tree.name, tree);
}
}
static private String GenCode( ArrExp tree, HashMap curScope)
{
ArrDec def = (ArrDec)inScopeAs(tree.name);
positiveIndex = true;
String type = GenCode(tree.index, curScope);
if ("int" != type)
System.out.println("Error line " + tree.pos + ": Array index must be int, got " + type);
else if (positiveIndex == false)
System.out.println("Error line " + tree.pos + ": Array index must be positive");
positiveIndex = true; //set it back to true to avoid propagating this error
if (def == null)
{
System.out.println("Error line " + tree.pos + ": Array Variable \"" + tree.name + "\" undefined");
return "err";
}
return def.type;
}*/
}