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
|
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "codegen.h"
#include "symboltable.h"
#include "stringbuffer.h"
extern void yyerror(char* msg);
static stringBuffer* staticVariableBuffer;
static stringBuffer* classInitBuffer;
static stringBuffer* currentMethodBuffer;
static stringBuffer* finishedMethodsBuffer;
static stringBuffer* mainBuffer;
static int currentMethodBufferIndex;
static int currentMethodStackSize;
static int currentMethodStackSizeMax;
static int currentMethodNumberOfLocals;
static int classInitBufferIndex;
static int classInitStackSize;
static int classInitStackSizeMax;
static int labelCounter = 0;
static int global = 1;
char tempString[MAX_LENGTH_OF_COMMAND];
extern char* className; /* from minako-syntax.y */
/* forward declarations */
static void increaseStackby(int stackdiff);
char convertType(int type);
void codegenInit() {
staticVariableBuffer = newStringBuffer();
classInitBuffer = newStringBuffer();
currentMethodBuffer = 0;
finishedMethodsBuffer = newStringBuffer();
mainBuffer = newStringBuffer();
stringBufferAppend(mainBuffer, "; ------- Header --------------------------------------------");
sprintf(tempString, ".class public synchronized %s", className);
stringBufferAppend(mainBuffer, tempString);
stringBufferAppend(mainBuffer, ".super java/lang/Object");
stringBufferAppend(mainBuffer, "; -----------------------------------------------------------");
stringBufferAppend(mainBuffer, "");
stringBufferAppend(finishedMethodsBuffer, "; ------- Constructor ---------------------------------------");
stringBufferAppend(finishedMethodsBuffer, ".method public <init>()V");
stringBufferAppend(finishedMethodsBuffer, "\t.limit stack 1");
stringBufferAppend(finishedMethodsBuffer, "\t.limit locals 1");
stringBufferAppend(finishedMethodsBuffer, "\taload_0");
stringBufferAppend(finishedMethodsBuffer, "\tinvokenonvirtual java/lang/Object/<init>()V");
stringBufferAppend(finishedMethodsBuffer, "\treturn");
stringBufferAppend(finishedMethodsBuffer, ".end method");
stringBufferAppend(finishedMethodsBuffer, "; -----------------------------------------------------------");
stringBufferAppend(finishedMethodsBuffer, "");
stringBufferAppend(staticVariableBuffer, "; ------- Class Variables -----------------------------------");
stringBufferAppend(classInitBuffer, "; ------- Class Initializer ---------------------------------");
stringBufferAppend(classInitBuffer, ".method static <clinit>()V");
classInitBufferIndex = classInitBuffer->numberOfNextElement;
stringBufferAppend(classInitBuffer, "\t.limit locals 0");
}
void codegenAppendCommand(char* cmd, int stackdiff) {
char tempString[MAX_LENGTH_OF_COMMAND];
sprintf(tempString, "\t%s", cmd);
if (global) stringBufferAppend(classInitBuffer, tempString);
else stringBufferAppend(currentMethodBuffer, tempString);
increaseStackby(stackdiff);
}
void codegenInsertCommand(int address, char* cmd, int stackdiff) {
char tempString[MAX_LENGTH_OF_COMMAND];
sprintf(tempString, "\t%s", cmd);
if (global) stringBufferInsert(classInitBuffer, address, tempString);
else stringBufferInsert(currentMethodBuffer, address, tempString);
increaseStackby(stackdiff);
}
void codegenAppendLabel(int label) {
char tempString[MAX_LENGTH_OF_COMMAND];
sprintf(tempString, "Label%d:", label);
if (global) stringBufferAppend(classInitBuffer, tempString);
else stringBufferAppend(currentMethodBuffer, tempString);
}
void codegenAddVariable(char* name, int type) {
/*fprintf(stderr, "add variable %s(%d) global=%d ", name, convertType(type), global);*/
if (global) {
if (type == TYPE_INT) sprintf(tempString, ".field static %s %c", name, 'I');
else if (type == TYPE_FLOAT) sprintf(tempString, ".field static %s %c", name, 'F');
else if (type == TYPE_BOOLEAN) sprintf(tempString, ".field static %s %c", name, 'Z');
else yyerror("compiler-intern error in codegenAddGlobalVariable().\n");
stringBufferAppend(staticVariableBuffer, tempString);
}
else {
currentMethodNumberOfLocals++;
}
}
int codegenGetNextLabel() {
return labelCounter++;
}
int codegenGetCurrentAddress() {
if (global) return classInitBuffer->numberOfNextElement;
else return currentMethodBuffer->numberOfNextElement;
}
void codegenEnterFunction(symtabEntry* entry) {
currentMethodBuffer = newStringBuffer();
currentMethodStackSize = 0;
currentMethodStackSizeMax = 0;
labelCounter = 1;
global = 0;
if (strcmp(entry->name, "main") == 0) {
if (entry->idtype != TYPE_VOID) yyerror("main has to be void.\n");
currentMethodNumberOfLocals = 1;
symtabInsert(strdup("#main-param#"), TYPE_VOID, CLASS_FUNC);
stringBufferAppend(currentMethodBuffer, "; ------- Methode ---- void main() --------------------------");
stringBufferAppend(currentMethodBuffer, ".method public static main([Ljava/lang/String;)V");
}
else {
int i;
currentMethodNumberOfLocals = entry->paramIndex;
stringBufferAppend(currentMethodBuffer, "; ------- Methode -------------------------------------------");
sprintf(tempString, ".method public static %s(", entry->name);
for (i=entry->paramIndex-1; i>=0; i--) {
int type = entry->params[i]->idtype;
tempString[strlen(tempString)+1] = 0;
tempString[strlen(tempString)] = convertType(type);
}
tempString[strlen(tempString)+2] = 0;
tempString[strlen(tempString)+1] = convertType(entry->idtype);
tempString[strlen(tempString)] = ')';
stringBufferAppend(currentMethodBuffer, tempString);
}
currentMethodBufferIndex = currentMethodBuffer->numberOfNextElement;
}
void codegenLeaveFunction() {
global = 1;
sprintf(tempString, "\t.limit locals %d", currentMethodNumberOfLocals);
stringBufferInsert(currentMethodBuffer, currentMethodBufferIndex, tempString);
sprintf(tempString, "\t.limit stack %d", currentMethodStackSizeMax);
stringBufferInsert(currentMethodBuffer, currentMethodBufferIndex, tempString);
stringBufferAppend(currentMethodBuffer, "\treturn");
stringBufferAppend(currentMethodBuffer, ".end method");
stringBufferAppend(currentMethodBuffer, "; -----------------------------------------------------------");
stringBufferAppend(currentMethodBuffer, "");
stringBufferConcatenate(finishedMethodsBuffer, currentMethodBuffer);
}
void codegenFinishCode() {
stringBufferAppend(staticVariableBuffer, "; -----------------------------------------------------------");
stringBufferAppend(staticVariableBuffer, "");
sprintf(tempString, "\t.limit stack %d", classInitStackSizeMax);
stringBufferInsert(classInitBuffer, classInitBufferIndex, tempString);
stringBufferAppend(classInitBuffer, "\treturn");
stringBufferAppend(classInitBuffer, ".end method");
stringBufferAppend(classInitBuffer, "; -----------------------------------------------------------");
stringBufferConcatenate(mainBuffer, staticVariableBuffer);
stringBufferConcatenate(mainBuffer, finishedMethodsBuffer);
stringBufferConcatenate(mainBuffer, classInitBuffer);
stringBufferPrint(mainBuffer);
}
static void increaseStackby(int stackdiff) {
if (global) {
classInitStackSize += stackdiff;
if (classInitStackSize > classInitStackSizeMax) classInitStackSizeMax = classInitStackSize;
}
else {
currentMethodStackSize += stackdiff;
if (currentMethodStackSize > currentMethodStackSizeMax) currentMethodStackSizeMax = currentMethodStackSize;
}
}
char convertType(int type) {
switch(type) {
case TYPE_VOID: return 'V';
case TYPE_INT: return 'I';
case TYPE_FLOAT: return 'F';
case TYPE_BOOLEAN: return 'Z';
default: yyerror("compiler-intern error in convertType().\n");
}
return 0; /* to avoid compiler-warning */
}
|