-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcodeWriter.cpp
110 lines (86 loc) · 2.87 KB
/
codeWriter.cpp
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
#include <iostream>
#include "codeWriter.h"
#include "helpers.h"
using namespace std;
CodeWriter::CodeWriter(ofstream& output)
: output{output}, counter{0}, currentCall{0}, currentFunction{""}
{
bootSP(output);
output << "@Sys.init" << endl;
output << "0;JMP" << endl;
}
void CodeWriter::writeArithmetic(const string& command)
{
if (command == "add") writeArithmeticAdd(output);
else if (command == "sub") writeArithmeticSub(output);
else if (command == "neg") writeArithmeticNeg(output);
else if (command == "eq") writeArithmeticEq(output, counter);
else if (command == "gt") writeArithmeticGt(output, counter);
else if (command == "lt") writeArithmeticLt(output, counter);
else if (command == "and") writeArithmeticAnd(output);
else if (command == "or") writeArithmeticOr(output);
else if (command == "not") writeArithmeticNot(output);
else throw invalid_argument("Invalid command from writeArithmetic()");
return;
}
void CodeWriter::writePushPop(CommandType commandType, const string& segment, const string& index)
{
if (commandType == CommandType::C_PUSH) pushToStack(output, segment, index);
else if (commandType == CommandType::C_POP) popToSeg(output, segment, index);
else throw invalid_argument("Invalid command type from writePushPop()");
return;
}
// TODO: Multiple functions?
void CodeWriter::writeLabel(const string& label)
{
output << "// LABEL" << endl;
output << "(" << currentFunction << "$" << label << ")" << endl;
}
void CodeWriter::writeGoto(const string& label)
{
output << "// GOTO" << endl;
output << "@" << currentFunction << "$" << label << endl;
output << "0;JMP" << endl;
}
void CodeWriter::writeIf(const string& label)
{
output << "// IF-GOTO" << endl;
popToD(output);
output << "@" << currentFunction << "$" << label << endl;
output << "D;JNE" << endl;
}
void CodeWriter::writeCall(const string& functionName, int numArgs)
{
output << "// CALL" << endl;
const string returnAddress = functionName + "$ret" + to_string(currentCall++);
pushCallerFrame(output, returnAddress);
setCalleePtrs(output, numArgs);
// goto the callee
output << "@" << functionName << endl;
output << "0;JMP" << endl;
// inject the return address label to the code
output << "(" << returnAddress << ")" << endl;
}
void CodeWriter::writeFunction(const string& functionName, int numLocals)
{
output << "// FUNCTION" << endl;
output << "(" << functionName << ")" << endl;
currentFunction = functionName;
for (int i = 0; i < numLocals; ++i) pushToStack(output, "constant", "0");
}
/**
* @brief Recover the environment of the caller function.
*
*
*/
void CodeWriter::writeReturn()
{
output << "// RETURN" << endl;
recoverCaller(output);
}
void CodeWriter::close()
{
writeInfiniteLoop(output);
output.close();
return;
}