-
Notifications
You must be signed in to change notification settings - Fork 1
/
codegen.h
189 lines (152 loc) · 8.48 KB
/
codegen.h
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
/* File: codegen.h
* ---------------
* The CodeGenerator class defines an object that will build Tac
* instructions (using the Tac class and its subclasses) and store the
* instructions in a sequential list, ready for further processing or
* translation to MIPS as part of final code generation.
*/
#ifndef _H_codegen
#define _H_codegen
#include "df_live_var.h"
#include <stdlib.h>
#include "list.h"
#include "tac.h"
#include <vector>
class FnDecl;
// These codes are used to identify the built-in functions
typedef enum { Alloc, ReadLine, ReadInteger, StringEqual,
PrintInt, PrintString, PrintBool, Halt, NumBuiltIns } BuiltIn;
class CodeGenerator {
friend class cfg_type;
private:
List<Instruction*> *code;
int curStackOffset, curGlobalOffset;
BeginFunc *insideFn;
public:
df_live_var analysis;
//int line_num;
// Here are some class constants to remind you of the offsets
// used for globals, locals, and parameters. You will be
// responsible for using these when assigning Locations.
// In a MIPS stack frame, first local is at fp-8, subsequent locals
// are at fp-12, fp-16, and so on. The first param is at fp+4,
// subsequent ones as fp+8, fp+12, etc. (Because methods have secret
// "this" passed in first param slot at fp+4, all normal params
// are shifted up by 4.) First global is at offset 0 from global
// pointer, all subsequent at +4, +8, etc.
// Conveniently, all vars are 4 bytes in size for code generation
static const int OffsetToFirstLocal = -8,
OffsetToFirstParam = 4,
OffsetToFirstGlobal = 0;
static const int VarSize = 4;
CodeGenerator();
// Assigns a new unique label name and returns it. Does not
// generate any Tac instructions (see GenLabel below if needed)
char *NewLabel();
// Creates and returns a Location for a new uniquely named
// temp variable. Does not generate any Tac instructions
Location *GenTempVar();
Location *GenLocalVariable(const char *varName);
Location *GenGlobalVariable(const char *varName);
// Generates Tac instructions to load a constant value. Creates
// a new temp var to hold the result. The constant
// value is passed as an integer, it can be 0 for integer zero,
// false for bool, NULL for null object, etc. All are just 4-byte
// zero in the code generation world.
// The second overloaded version is used for string constants.
// The LoadLabel method loads a label into a temporary.
// Each of the methods returns a Location for the temp var
// where the constant was loaded.
Location *GenLoadConstant(int value);
Location *GenLoadConstant(const char *str);
Location *GenLoadLabel(const char *label);
// Generates Tac instructions to copy value from one location to another
void GenAssign(Location *dst, Location *src);
// Generates Tac instructions to dereference addr and store value
// into that memory location. addr should hold a valid memory address
// (most likely computed from an array or field offset calculation).
// The optional offset argument can be used to offset the addr by a
// positive/negative number of bytes. If not given, 0 is assumed.
void GenStore(Location *addr, Location *val, int offset = 0);
// Generates Tac instructions to dereference addr and load contents
// from a memory location into a new temp var. addr should hold a
// valid memory address (most likely computed from an array or
// field offset calculation). Returns the Location for the new
// temporary variable where the result was stored. The optional
// offset argument can be used to offset the addr by a positive or
// negative number of bytes. If not given, 0 is assumed.
Location *GenLoad(Location *addr, int offset = 0);
// Generates Tac instructions to perform one of the binary ops
// identified by string name, such as "+" or "==". Returns a
// Location object for the new temporary where the result
// was stored.
Location *GenBinaryOp(const char *opName, Location *op1, Location *op2);
// Generates the Tac instruction for pushing a single
// parameter. Used to set up for ACall and LCall instructions.
// The Decaf convention is that parameters are pushed right
// to left (so the first argument is pushed last)
void GenPushParam(Location *param);
// Generates the Tac instruction for popping parameters to
// clean up after an ACall or LCall instruction. All parameters
// are removed with one adjustment of the stack pointer.
void GenPopParams(int numBytesOfParams);
// Generates the Tac instructions for a LCall, a jump to
// a compile-time label. The params to the target routine
// should already have been pushed. If hasReturnValue is
// true, a new temp var is created, the fn result is stored
// there and that Location is returned. If false, no temp is
// created and NULL is returned
Location *GenLCall(const char *label, bool fnHasReturnValue);
// Generates the Tac instructions for ACall, a jump to an
// address computed at runtime. Works similarly to LCall,
// described above, in terms of return type.
// The fnAddr Location is expected to hold the address of
// the code to jump to (typically it was read from the vtable)
Location *GenACall(Location *fnAddr, bool fnHasReturnValue);
// Generates the Tac instructions to call one of
// the built-in functions (Read, Print, Alloc, etc.) Although
// you could just make a call to GenLCall above, this cover
// is a little more convenient to use. The arguments to the
// builtin should be given as arg1 and arg2, NULL is used if
// fewer than 2 args to pass. The method returns a Location
// for the new temp var holding the result. For those
// built-ins with no return value (Print/Halt), no temporary
// is created and NULL is returned.
Location *GenBuiltInCall(BuiltIn b, Location *arg1 = NULL, Location *arg2 = NULL);
// These methods generate the Tac instructions for various
// control flow (branches, jumps, returns, labels)
// One minor detail to mention is that you can pass NULL
// (or omit arg) to GenReturn for a return that does not
// return a value
void GenIfZ(Location *test, const char *label);
void GenGoto(const char *label);
void GenReturn(Location *val = NULL);
void GenLabel(const char *label);
// These methods generate the Tac instructions that mark the start
// and end of a function/method definition.
BeginFunc *GenBeginFunc(FnDecl *fn);
void GenEndFunc();
// Generates the Tac instructions for defining vtable for a
// The methods parameter is expected to contain the vtable
// methods in the order they should be laid out. The vtable
// is tagged with a label of the class name, so when you later
// need access to the vtable, you use LoadLabel of class name.
void GenVTable(const char *className, List<const char*> *methodLabels);
// Emits the final "object code" for the program by
// translating the sequence of Tac instructions into their mips
// equivalent and printing them out to stdout. If the debug
// flag tac is on (-d tac), it will not translate to MIPS,
// but instead just print the untranslated Tac. It may be
// useful in debugging to first make sure your Tac is correct.
void DoFinalCodeGen();
Location *GenNewArray(Location *numElements);
Location *GenArrayLen(Location *array);
Location *GenNew(const char *vTableLabel, int instanceSize);
Location *GenDynamicDispatch(Location *obj, int vtableOffset, List<Location*> *args, bool hasReturnValue);
Location *GenSubscript(Location *array, Location *index);
Location *GenFunctionCall(const char *fnLabel, List<Location*> *args, bool hasReturnValue);
// private helper, not for public user
Location *GenMethodCall(Location*rcvr, Location*meth, List<Location*> *args, bool hasReturnValue);
void GenHaltWithMessage(const char *msg);
};
#endif