Project restucture with IR and CG
This commit is contained in:
17
Makefile
17
Makefile
@ -10,8 +10,7 @@ LEX := src/lexicalStructure.lex
|
||||
YACC := src/grammar.y
|
||||
EXE := alpha
|
||||
|
||||
OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o
|
||||
# tmp/intermediate_code.o codegen.o <--- Add to line above
|
||||
OBJS := tmp/runner.o tmp/symbol_table.o tmp/grammar.tab.o tmp/lex.yy.o tmp/intermediate_code.o tmp/codegen.o
|
||||
|
||||
TESTS-S1 := $(wildcard tests/sprint1/test/*.alpha)
|
||||
TESTS-S2 := $(wildcard tests/sprint2/test/*.alpha)
|
||||
@ -31,6 +30,7 @@ clean:
|
||||
rm -f $(EXE)
|
||||
rm -rf out
|
||||
rm -rf tmp
|
||||
rm -f *.s
|
||||
|
||||
tmp:
|
||||
mkdir -p tmp
|
||||
@ -55,13 +55,11 @@ tmp/lex.yy.o: tmp/lex.yy.c
|
||||
tmp/symbol_table.o: src/symbol_table.c src/symbol_table.h
|
||||
$(CC) $(CFLAGS) -c src/symbol_table.c -o tmp/symbol_table.o
|
||||
|
||||
# Uncomment rules when ready
|
||||
tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h
|
||||
$(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o
|
||||
|
||||
# tmp/intermediate_code.o: src/intermediate_code.c src/intermediate_code.h
|
||||
# $(CC) $(CFLAGS) -c src/intermediate_code.c -o tmp/intermediate_code.o
|
||||
|
||||
# tmp/codegen.o: src/codegen.c src/codegen.h
|
||||
# $(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o
|
||||
tmp/codegen.o: src/codegen.c src/codegen.h
|
||||
$(CC) $(CFLAGS) -c src/codegen.c -o tmp/codegen.o
|
||||
|
||||
tmp/runner.o: src/runner.c src/runner.h tmp/flex.h tmp/grammar.tab.h
|
||||
$(CC) $(CFLAGS) -c src/runner.c -o tmp/runner.o
|
||||
@ -102,7 +100,4 @@ test-s4:
|
||||
chmod +x ./test.sh
|
||||
./test.sh sp4
|
||||
./check.sh sp4
|
||||
|
||||
# Temprorary test ~ Scarlett
|
||||
test-make: clean tmp tmp/grammar.tab.c tmp/grammar.tab.h tmp/lex.yy.c tmp/flex.h tmp/grammar.tab.o tmp/lex.yy.o tmp/symbol_table.o tmp/runner.o
|
||||
# -----------
|
590
src/codegen.c
590
src/codegen.c
@ -0,0 +1,590 @@
|
||||
#include "codegen.h"
|
||||
|
||||
int generate() {
|
||||
offset = 0;
|
||||
Instruction *i = begin;
|
||||
while (i != NULL) {
|
||||
switch (getOp(i)) {
|
||||
case E_LABEL:
|
||||
generateLabel(i);
|
||||
break;
|
||||
case E_ADD:
|
||||
generateAdd(i);
|
||||
break;
|
||||
case E_SUB:
|
||||
generateSub(i);
|
||||
break;
|
||||
case E_MUL:
|
||||
generateMult(i);
|
||||
break;
|
||||
case E_DIV:
|
||||
generateDiv(i);
|
||||
break;
|
||||
case E_MOD:
|
||||
generateMod(i);
|
||||
break;
|
||||
case E_OR:
|
||||
generateOr(i);
|
||||
break;
|
||||
case E_AND:
|
||||
generateAnd(i);
|
||||
break;
|
||||
case E_NEG:
|
||||
generateNeg(i);
|
||||
break;
|
||||
case E_NOT:
|
||||
generateNot(i);
|
||||
break;
|
||||
case E_ASSIGN:
|
||||
generateAssign(i);
|
||||
break;
|
||||
case E_GOTO:
|
||||
generateGoto(i);
|
||||
break;
|
||||
case E_IF_X_TRUE:
|
||||
generateIfTrue(i);
|
||||
break;
|
||||
case E_IF_X_FALSE:
|
||||
generateIfFalse(i);
|
||||
break;
|
||||
case E_LESS_THAN:
|
||||
generateLessThan(i);
|
||||
break;
|
||||
case E_EQUAL_TO:
|
||||
generateEqualTo(i);
|
||||
break;
|
||||
case E_CALL:
|
||||
generateCall(i);
|
||||
break;
|
||||
case E_PARAM:
|
||||
generateParam(i);
|
||||
break;
|
||||
case E_RETURN:
|
||||
generateReturn(i);
|
||||
break;
|
||||
case E_INDEX_COPY_RIGHT:
|
||||
generateCopyRight(i);
|
||||
break;
|
||||
case E_INDEX_COPY_LEFT:
|
||||
generateCopyLeft(i);
|
||||
break;
|
||||
case E_ADDRESS_OF:
|
||||
generateAddressOf(i);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
i = i->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
CGNode *getNextCG(CGNode *cg) {
|
||||
if (cg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return cg->next;
|
||||
}
|
||||
|
||||
int getAddress(CGNode *cg) {
|
||||
if (cg == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return currentsp - cg->address;
|
||||
}
|
||||
|
||||
TableNode *getTNofCG(CGNode *cg) {
|
||||
if (cg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return cg->tn;
|
||||
}
|
||||
|
||||
CGNode *findCG(TableNode *tn) {
|
||||
CGNode *cg = cgList;
|
||||
while (cg != NULL) {
|
||||
if (getTNofCG(cg) == tn) {
|
||||
return cg;
|
||||
}
|
||||
cg = getNextCG(cg);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CGNode *addCG(TableNode *tn, int sp) {
|
||||
CGNode *cg = calloc(1, sizeof(CGNode));
|
||||
cg->tn = tn;
|
||||
cg->address = sp;
|
||||
offset += getPrimSize(tn); //not sure if this is the correct amount to add to the offset
|
||||
cg->next = cgList;
|
||||
cgList = cg;
|
||||
return cg;
|
||||
}
|
||||
|
||||
int generateLabel(Instruction *inst) {
|
||||
fprintf(cg_flag, ".L%d:\n", getLabel(inst));
|
||||
return 0;
|
||||
}
|
||||
int generateAdd(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateAdd failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op1));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op1)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\taddl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateSub(Instruction *instruction) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(instruction);
|
||||
TNodeOrConst *op2 = getOperand2(instruction);
|
||||
CGNode *cg = findCG(getResult(instruction));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateSub failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(instruction), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateSub failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateAdd failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tsubl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateMult(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateMult failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateMult failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateMult failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tsubl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateDiv(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateDiv failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateDiv failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateDiv failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); //moves dividend into eax
|
||||
fprintf(cg_flag, "\tcltd\n"); //sign extends the dividend in eax
|
||||
fprintf(cg_flag, "\tidivl\t%d(%%rbp)\n", getAddress(op2CG)); //divides edx by value accessed from stack
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); //stores result
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateMod(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateMod failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateMod failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateMod failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG)); //moves dividend into eax
|
||||
fprintf(cg_flag, "\tcltd\n"); //sign extends the dividend in eax
|
||||
fprintf(cg_flag, "\tidivl\t%d(%%rbp)\n", getAddress(op2CG)); //divides edx by value accessed from stack
|
||||
fprintf(cg_flag, "\tmovl\t%%edx, %d(%%rbp)\n", getAddress(cg)); //stores result from edx (remainder)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateOr(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateOr failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateOr failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateOr failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\torll\t%d(%%rbp), %%eax\n", getAddress(op2CG)); //divides edx by value accessed from stack
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg)); //stores result
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateAnd(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("%sgenerateAnd failed, NULL operand", COLOR_RED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateAnd failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateAnd failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tandl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
int generateNeg(Instruction *inst) {
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateNeg failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateNeg failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateNeg failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tnegl\t%d %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
int generateNot(Instruction *inst) {
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("generateNot failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateNot failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateNot failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tnotl\t%%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateAssign(Instruction *inst) {
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL) {
|
||||
printdebug("generateAssign failed, NULL operand");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
//add option for constant assignment (should be easy)
|
||||
if (isConst(op1) == true) {
|
||||
fprintf(cg_flag, "\tmovl\t$%d, %d(%%rbp)\n", getConst(op1), getAddress(cg));
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateAssign failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tmovl\t%%eax, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateGoto(Instruction *instruction) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int generateCondGoto(Instruction *instruction) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int generateIfTrue(Instruction *instruction) {
|
||||
return -1;
|
||||
// might just be a goto for where to go if something is true, or returning if something is true, or checking if true and writing goto if thats the case
|
||||
}
|
||||
|
||||
int generateIfFalse(Instruction *instruction) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int generateLessThan(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("%sgenerateLessThan failed, NULL operand", COLOR_RED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateLessThan failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tsetl\t%%al\n");
|
||||
fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int generateEqualTo(Instruction *inst) {
|
||||
/*
|
||||
Both immediate:
|
||||
One immediate:
|
||||
Neither immediate:
|
||||
*/
|
||||
TNodeOrConst *op1 = getOperand1(inst);
|
||||
TNodeOrConst *op2 = getOperand2(inst);
|
||||
CGNode *cg = findCG(getResult(inst));
|
||||
|
||||
if (op1 == NULL || op2 == NULL) {
|
||||
printdebug("%sgenerateLessThan failed, NULL operand", COLOR_RED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cg == NULL) {
|
||||
cg = addCG(getResult(inst), offset);
|
||||
}
|
||||
|
||||
CGNode *op1CG = findCG(getTN(op1));
|
||||
CGNode *op2CG = findCG(getTN(op2));
|
||||
if (op1CG == NULL) {
|
||||
printdebug("generateLessThan failed, op1 is not constant but not in CGlist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (op2CG == NULL) {
|
||||
printdebug("generateLessThan failed, %s is not initialized/in CG", getName(getTN(op2)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(cg_flag, "\tmovl\t%d(%%rbp), %%eax\n", getAddress(op1CG));
|
||||
fprintf(cg_flag, "\tcmpl\t%d(%%rbp), %%eax\n", getAddress(op2CG));
|
||||
fprintf(cg_flag, "\tsete\t%%al\n");
|
||||
fprintf(cg_flag, "\tmovb\t%%al, %d(%%rbp)\n", getAddress(cg));
|
||||
return 0;
|
||||
}
|
||||
int generateCall(Instruction *instruction) {
|
||||
return -1;
|
||||
//will want to store parameters and then update the offset by adding 8? for stack pointer stuff, can then print call subroutine name, followed by movl of the result into the result's cg
|
||||
}
|
||||
int generateReturn(Instruction *instruction) {
|
||||
return -1;
|
||||
//will movl the result into the appropriate register and move the stack pointer/offset stuff back to correct value
|
||||
}
|
||||
int generateCopyRight(Instruction *instruction) {
|
||||
return -1;
|
||||
}
|
||||
int generateCopyLeft(Instruction *instruction) {
|
||||
return -1;
|
||||
}
|
||||
int generateAddressOf(Instruction *instruction) {
|
||||
return -1;
|
||||
}
|
||||
int generateParam(Instruction *instruction) {
|
||||
//need to check if op1 is null, then add it to the appropriate register/cg node. need a way to keep track of this, maybe just have global count of params generated
|
||||
return -1;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "intermediate_code.h"
|
||||
#include "symbol_table.h"
|
||||
|
||||
extern FILE *cg_flag;
|
||||
|
||||
typedef struct CGNode {
|
||||
TableNode *tn;
|
||||
int address;
|
||||
CGNode *next;
|
||||
} CGNode;
|
||||
|
||||
int generate();
|
||||
CGNode *getNextCG(CGNode *cg);
|
||||
int getAddress(CGNode *cg);
|
||||
TableNode *getTNofCG(CGNode *cg);
|
||||
CGNode *findCG(TableNode *tn);
|
||||
CGNode *addCG(TableNode *tn, int sp);
|
||||
int generateLabel(Instruction *inst);
|
||||
int generateAdd(Instruction *inst);
|
||||
int generateSub(Instruction *instruction);
|
||||
int generateMult(Instruction *inst);
|
||||
int generateDiv(Instruction *inst);
|
||||
int generateMod(Instruction *inst);
|
||||
int generateOr(Instruction *inst);
|
||||
int generateAnd(Instruction *inst);
|
||||
int generateNeg(Instruction *inst);
|
||||
int generateNot(Instruction *inst);
|
||||
int generateAssign(Instruction *inst);
|
||||
int generateGoto(Instruction *instruction);
|
||||
int generateCondGoto(Instruction *instruction);
|
||||
int generateIfTrue(Instruction *instruction);
|
||||
int generateIfFalse(Instruction *instruction);
|
||||
int generateLessThan(Instruction *inst);
|
||||
int generateEqualTo(Instruction *inst);
|
||||
int generateCall(Instruction *instruction);
|
||||
int generateReturn(Instruction *instruction);
|
||||
int generateCopyRight(Instruction *instruction);
|
||||
int generateCopyLeft(Instruction *instruction);
|
||||
int generateAddressOf(Instruction *instruction);
|
||||
int generateParam(Instruction *instruction);
|
||||
|
||||
extern int label_count;
|
||||
extern Instruction *begin;
|
||||
extern Instruction *current;
|
||||
|
||||
extern int offset;
|
||||
extern int currentsp;
|
||||
extern CGNode *cgList;
|
28
src/grammar.h
Normal file
28
src/grammar.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "../src/codegen.h"
|
||||
#include "../src/intermediate_code.h"
|
||||
#include "../src/symbol_table.h"
|
||||
extern FILE *asc_flag;
|
||||
extern bool tc_flag;
|
||||
|
||||
typedef enum {
|
||||
ERROR_RUNTIME = 1,
|
||||
ERROR_SYNTAX = 2,
|
||||
ERROR_TYPE = 3,
|
||||
ERROR_UNDEFINED = 4
|
||||
} ErrorType;
|
||||
|
||||
int token_tracker;
|
||||
TableNode *tn;
|
||||
|
||||
void yyerror(const char *err);
|
||||
void throw_error(ErrorType error_type, const char *format, ...);
|
||||
|
||||
int label_count;
|
||||
Instruction *begin;
|
||||
Instruction *current;
|
||||
|
||||
int offset;
|
||||
int currentsp;
|
||||
CGNode *cgList;
|
@ -17,22 +17,7 @@
|
||||
// Please ask Scarlett if you are unsure of how to format something. Thanks! 😀
|
||||
|
||||
%{
|
||||
#include "../src/symbol_table.h"
|
||||
extern FILE *asc_flag;
|
||||
extern bool tc_flag;
|
||||
|
||||
typedef enum {
|
||||
ERROR_RUNTIME = 1,
|
||||
ERROR_SYNTAX = 2,
|
||||
ERROR_TYPE = 3,
|
||||
ERROR_UNDEFINED = 4
|
||||
} ErrorType;
|
||||
|
||||
int token_tracker;
|
||||
TableNode * tn;
|
||||
|
||||
void yyerror(const char *err);
|
||||
void throw_error(ErrorType error_type, const char *format, ...);
|
||||
#include "../src/grammar.h"
|
||||
%}
|
||||
|
||||
%union {
|
||||
@ -630,7 +615,7 @@ expression:
|
||||
$$ = node;
|
||||
} else {
|
||||
$$=undefined;
|
||||
error_type(getTypeEntry((TableNode*)$2), integ, "");
|
||||
throw_error(ERROR_TYPE, "%s != %s", getName(getTypeEntry((TableNode*)$2)), getName(integ));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,399 @@
|
||||
#include "intermediate_code.h"
|
||||
|
||||
// TODO: this is here to bring your attention to the comment bellow.
|
||||
// check if start is NULL if it is assign it to the start globle variable
|
||||
// otherwise make it next of current and set cur to your instruction.
|
||||
TNodeOrConst* getOperand1(Instruction* i) {
|
||||
return i->operand1;
|
||||
}
|
||||
|
||||
TNodeOrConst* getOperand2(Instruction* i) {
|
||||
return i->operand2;
|
||||
}
|
||||
|
||||
TableNode* getResult(Instruction* i) {
|
||||
return i->result;
|
||||
}
|
||||
|
||||
Op getOp(Instruction* i) {
|
||||
return i->opcode;
|
||||
}
|
||||
|
||||
int getLabel(Instruction* i) {
|
||||
return i->label;
|
||||
}
|
||||
|
||||
int get_index(Instruction* i) {
|
||||
return i->index;
|
||||
}
|
||||
|
||||
void set_label(Instruction* i, int label) {
|
||||
i->label = label;
|
||||
}
|
||||
|
||||
bool isConst(TNodeOrConst* tnc) {
|
||||
return tnc->d != NODE;
|
||||
}
|
||||
|
||||
TNodeOrConst* tn_or_const(Discriminant d, void* tnc) {
|
||||
TNodeOrConst* count = calloc(1, sizeof(*count));
|
||||
count->d = d;
|
||||
count->tnc_union = calloc(1, sizeof(*count->tnc_union));
|
||||
switch (d) {
|
||||
case NODE:
|
||||
count->tnc_union->node = tnc;
|
||||
break;
|
||||
case ADDRESS:
|
||||
count->tnc_union->address = tnc;
|
||||
break;
|
||||
case STRING:
|
||||
count->tnc_union->string = tnc;
|
||||
break;
|
||||
case INTEGER:
|
||||
count->tnc_union->integer = *(int*)tnc;
|
||||
break;
|
||||
case CHARACTER:
|
||||
count->tnc_union->character = *(char*)tnc;
|
||||
break;
|
||||
case BOOLEAN:
|
||||
count->tnc_union->Boolean = *(uint_least8_t*)tnc;
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void emit_helper(void) {
|
||||
Instruction* inst = calloc(1, sizeof(*inst));
|
||||
if (begin == NULL) {
|
||||
begin = current = inst;
|
||||
current->index = 1;
|
||||
} else {
|
||||
current->next = inst;
|
||||
inst->prev = current;
|
||||
inst->index = current->index + 1;
|
||||
current = inst;
|
||||
}
|
||||
}
|
||||
|
||||
void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2) {
|
||||
emit_helper();
|
||||
current->opcode = op;
|
||||
// TODO: create temp and remove result from param list
|
||||
current->result = result;
|
||||
current->operand1 = arg1;
|
||||
current->operand2 = arg2;
|
||||
}
|
||||
|
||||
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg) {
|
||||
emit_helper();
|
||||
current->opcode = op;
|
||||
current->result = result;
|
||||
current->operand1 = arg;
|
||||
}
|
||||
|
||||
void emit_assignment(TableNode* target, TNodeOrConst* source) {
|
||||
emit_helper();
|
||||
current->opcode = E_ASSIGN;
|
||||
current->result = target;
|
||||
current->operand1 = source;
|
||||
}
|
||||
|
||||
char* get_string(TNodeOrConst* tc) {
|
||||
char* s;
|
||||
switch (tc->d) {
|
||||
case NODE:
|
||||
return getName(tc->tnc_union->node);
|
||||
case ADDRESS:
|
||||
return strdup("null");
|
||||
case STRING:
|
||||
return tc->tnc_union->string;
|
||||
case INTEGER:
|
||||
s = calloc(10, sizeof(char));
|
||||
sprintf(s, "%d", tc->tnc_union->integer);
|
||||
return s;
|
||||
case CHARACTER:
|
||||
s = calloc(2, sizeof(char));
|
||||
sprintf(s, "%c", tc->tnc_union->character);
|
||||
return s;
|
||||
case BOOLEAN:
|
||||
if (tc->tnc_union->Boolean) {
|
||||
return strdup("true");
|
||||
}
|
||||
return strdup("false");
|
||||
}
|
||||
}
|
||||
|
||||
void emit_as_file(FILE* out_file, Instruction* i) {
|
||||
if (i == NULL) {
|
||||
return;
|
||||
}
|
||||
switch (i->opcode) {
|
||||
case E_LABEL:
|
||||
break;
|
||||
// this is a terrible one to start with
|
||||
// fprintf(out_file, "%04.d: %d ", i->index, i->label);
|
||||
case E_ADD:
|
||||
fprintf(out_file, "%4.d: %s = %s + %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_SUB:
|
||||
fprintf(out_file, "%4.d: %s = %s - %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_MUL:
|
||||
fprintf(out_file, "%4.d: %s = %s * %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_DIV:
|
||||
fprintf(out_file, "%4.d: %s = %s / %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_MOD:
|
||||
fprintf(out_file, "%4.d: %s = %s %% %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_OR:
|
||||
fprintf(out_file, "%4.d: %s = %s | %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_AND:
|
||||
fprintf(out_file, "%4.d: %s = %s & %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
case E_NEG:
|
||||
fprintf(out_file, "%4.d: %s = -%s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1));
|
||||
break;
|
||||
case E_NOT:
|
||||
fprintf(out_file, "%4.d: %s = !%s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1));
|
||||
break;
|
||||
case E_ASSIGN:
|
||||
fprintf(out_file, "%4.d: %s = %s\n",
|
||||
i->index, getName(i->result),
|
||||
get_string(i->operand1));
|
||||
break;
|
||||
case E_GOTO:
|
||||
// are we ever going to use this?
|
||||
// yes we do look at bounds checking
|
||||
case E_IF_X_TRUE:
|
||||
fprintf(out_file, "%4.d: if %s goto %d\n",
|
||||
i->index, get_string(i->operand1),
|
||||
i->label);
|
||||
break;
|
||||
case E_IF_X_FALSE:
|
||||
fprintf(out_file, "%4.d: if %s false goto %d\n",
|
||||
i->index, get_string(i->operand1),
|
||||
i->label);
|
||||
break;
|
||||
case E_LESS_THAN:
|
||||
fprintf(out_file, "%4.d: if %s < %s goto %d\n",
|
||||
i->index, get_string(i->operand1),
|
||||
get_string(i->operand2), i->label);
|
||||
break;
|
||||
case E_EQUAL_TO:
|
||||
fprintf(out_file, "%4.d: if %s = %s goto %d\n",
|
||||
i->index, get_string(i->operand1),
|
||||
get_string(i->operand2), i->label);
|
||||
break;
|
||||
case E_CALL:
|
||||
fprintf(out_file, "%4.d: call %s %s\n",
|
||||
i->index, get_string(i->operand1),
|
||||
get_string(i->operand2));
|
||||
break;
|
||||
|
||||
case E_PARAM:
|
||||
fprintf(out_file, "%4.d: param %s \n",
|
||||
i->index, get_string(i->operand1));
|
||||
break;
|
||||
case E_RETURN:
|
||||
|
||||
case E_INDEX_COPY_RIGHT:
|
||||
case E_INDEX_COPY_LEFT:
|
||||
|
||||
case E_ADDRESS_OF:
|
||||
|
||||
case E_DEREF_RIGHT:
|
||||
case E_DEREF_LEFT:
|
||||
}
|
||||
|
||||
emit_as_file(out_file, i->next);
|
||||
}
|
||||
|
||||
void emit_label(int label) {
|
||||
emit_helper();
|
||||
current->opcode = E_LABEL;
|
||||
current->label = label;
|
||||
}
|
||||
|
||||
void emit_jump(int label) {
|
||||
emit_helper();
|
||||
current->opcode = E_GOTO;
|
||||
current->label = label;
|
||||
}
|
||||
|
||||
void emit_conditional_jump(Op condition, int label, ...) {
|
||||
// when this instruction is a conditional jump then the imput looks like (Op, int, TNodeOrConst *).
|
||||
// when the inst is a cond with a Relational operation then the input looks like (Op, int, TNodeOrConst *, TNodeOrConst *)
|
||||
emit_helper();
|
||||
va_list argptr;
|
||||
va_start(argptr, label);
|
||||
current->opcode = condition;
|
||||
current->label = label;
|
||||
TNodeOrConst* n1;
|
||||
TNodeOrConst* n2;
|
||||
switch (condition) {
|
||||
case E_IF_X_TRUE:
|
||||
case E_IF_X_FALSE:
|
||||
n1 = va_arg(argptr, TNodeOrConst*);
|
||||
current->operand1 = n1;
|
||||
break;
|
||||
case E_LESS_THAN:
|
||||
case E_EQUAL_TO:
|
||||
n1 = va_arg(argptr, TNodeOrConst*);
|
||||
n2 = va_arg(argptr, TNodeOrConst*);
|
||||
current->operand1 = n1;
|
||||
current->operand2 = n2;
|
||||
break;
|
||||
}
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void emit_function_start(int name) {
|
||||
emit_helper();
|
||||
current->opcode = E_LABEL; // I think this is right TODO: ask
|
||||
current->label = name;
|
||||
// this is probabaly a func decleration
|
||||
}
|
||||
|
||||
void emit_parameter(TNodeOrConst* param) {
|
||||
emit_helper();
|
||||
current->opcode = E_PARAM;
|
||||
current->operand1 = param;
|
||||
}
|
||||
|
||||
void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name) {
|
||||
emit_helper();
|
||||
current->opcode = E_CALL;
|
||||
current->operand1 = tn_or_const(INTEGER, ¶m_count);
|
||||
current->operand2 = name;
|
||||
current->result = result;
|
||||
}
|
||||
|
||||
void emit_return(TNodeOrConst* value) {
|
||||
emit_helper();
|
||||
current->opcode = E_RETURN;
|
||||
current->operand1 = value;
|
||||
}
|
||||
|
||||
void emit_reserve(TableNode* result, TNodeOrConst* size) {
|
||||
emit_parameter(size);
|
||||
emit_function_call(result, 1, tn_or_const(NODE, look_up(cur, "reserve")));
|
||||
}
|
||||
|
||||
void emit_release(TableNode* pointer) {
|
||||
emit_parameter(tn_or_const(NODE, pointer));
|
||||
emit_function_call(pointer, 1, tn_or_const(NODE, look_up(cur, "release")));
|
||||
}
|
||||
|
||||
void emit_deref_right() {
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_deref_left() {
|
||||
return;
|
||||
}
|
||||
|
||||
void emit_field_access(char* result, char* record, char* field) {
|
||||
emit_helper();
|
||||
}
|
||||
|
||||
void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index) {
|
||||
emit_helper();
|
||||
current->opcode;
|
||||
current->result = result;
|
||||
current->operand1 = array;
|
||||
current->operand2 = index;
|
||||
// TODO: Still don't know what to do with the dimentions
|
||||
}
|
||||
|
||||
void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr) {
|
||||
/*
|
||||
{[string: 5]
|
||||
.
|
||||
.
|
||||
s:= reserve s(5);
|
||||
s(0) := 'H';
|
||||
s(1) := 'e';
|
||||
.
|
||||
.
|
||||
s._0 num of dims Known at compile time
|
||||
s._1 size Known at run time
|
||||
s._1 int | 1 byte
|
||||
+-------+---+---+---+---+---+
|
||||
| 5 | H | e | l | l | o |
|
||||
+-------+---+---+---+---+---+
|
||||
size
|
||||
^
|
||||
|
|
||||
p
|
||||
s._0 ok
|
||||
s._1 ok
|
||||
s._2 not ok
|
||||
t_0 is index
|
||||
t_1 = *(int *)p = s._1
|
||||
if t_0 < 0 GOTO ERROR
|
||||
if t_0 < s._1 GOTO access array
|
||||
GOTO ERROR
|
||||
*/
|
||||
//emit_conditional_jump(E_LESS_THAN, );
|
||||
//emit_conditional_jump(E_LESS_THAN, );
|
||||
//emit_jump();
|
||||
/* We need a label ERROR to jump to
|
||||
*/
|
||||
}
|
||||
|
||||
/*// * Implement temp variable generator function that produces unique names (t1, t2, etc.)
|
||||
char * temp_var_gen(){
|
||||
char * ret = calloc(9, sizeof(*ret));
|
||||
sprintf(ret, "$t%d", temp_count);
|
||||
temp_count++;
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
char* label_gen() {
|
||||
char* ret = calloc(9, sizeof(*ret));
|
||||
sprintf(ret, "L_%d", label_count);
|
||||
label_count++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
TableNode* getTN(TNodeOrConst* tnc) {
|
||||
if (tnc->d == NODE) {
|
||||
return tnc->tnc_union->node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
//we must fix this
|
||||
int getConst(TNodeOrConst* tnc) {
|
||||
if (tnc->d == INTEGER) {
|
||||
return tnc->tnc_union->integer;
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "symbol_table.h"
|
||||
|
||||
// these are from page 364
|
||||
typedef enum {
|
||||
E_LABEL = 10000, // this is not in the book
|
||||
E_ADD, // 1 from the list
|
||||
E_SUB, // 1
|
||||
E_MUL, // 1
|
||||
E_DIV, // 1
|
||||
E_MOD, // 1
|
||||
E_OR, // 1
|
||||
E_AND, // 1
|
||||
E_NEG, // 2
|
||||
E_NOT, // 2
|
||||
E_ASSIGN, // 3
|
||||
E_GOTO, // 4
|
||||
E_COND_GOTO, // 5 I don't thik I need this because we could just follow the < or the = and just assume that it's a cond got
|
||||
E_IF_X_TRUE, // 5
|
||||
E_IF_X_FALSE, // 5
|
||||
E_LESS_THAN, // 6 rule 1 + 5
|
||||
E_EQUAL_TO, // 6 rule 1 + 5
|
||||
E_CALL, // 7
|
||||
E_PARAM, // 7
|
||||
E_RETURN, // 7
|
||||
E_INDEX_COPY_RIGHT, // 8 this is x = y[i]
|
||||
E_INDEX_COPY_LEFT, // 8 x[i] = y
|
||||
E_ADDRESS_OF, // 9 x = &y
|
||||
E_DEREF_RIGHT, // 9 x = *y
|
||||
E_DEREF_LEFT // 9 x* = y
|
||||
} Op;
|
||||
|
||||
typedef enum {
|
||||
NODE = 11000, // TableNode
|
||||
INTEGER, // int
|
||||
STRING, // char *
|
||||
CHARACTER, // char
|
||||
ADDRESS, // void *
|
||||
BOOLEAN // bool
|
||||
} Discriminant;
|
||||
|
||||
typedef union {
|
||||
TableNode* node;
|
||||
int integer;
|
||||
char* string;
|
||||
char character;
|
||||
void* address;
|
||||
bool Boolean;
|
||||
} TNConstUnion;
|
||||
|
||||
typedef struct {
|
||||
Discriminant d;
|
||||
TNConstUnion* tnc_union;
|
||||
} TNodeOrConst;
|
||||
|
||||
typedef struct Instruction Instruction;
|
||||
typedef struct Instruction {
|
||||
Op opcode;
|
||||
TableNode* result;
|
||||
TNodeOrConst* operand1;
|
||||
TNodeOrConst* operand2;
|
||||
int label;
|
||||
int index;
|
||||
|
||||
Instruction* prev;
|
||||
Instruction* next;
|
||||
} Instruction;
|
||||
|
||||
typedef struct TFList {
|
||||
Instruction* i;
|
||||
TFList* next;
|
||||
} TFList;
|
||||
|
||||
TNodeOrConst* getOperand1(Instruction* i);
|
||||
TNodeOrConst* getOperand2(Instruction* i);
|
||||
TableNode* getResult(Instruction* i);
|
||||
Op getOp(Instruction* i);
|
||||
int getLabel(Instruction* i);
|
||||
int get_index(Instruction* i);
|
||||
void set_label(Instruction* i, int label);
|
||||
bool isConst(TNodeOrConst* tnc);
|
||||
TNodeOrConst* tn_or_const(Discriminant d, void* tnc);
|
||||
static void emit_helper(void);
|
||||
void emit_binary_op(Op op, TableNode* result, TNodeOrConst* arg1, TNodeOrConst* arg2);
|
||||
void emit_unary_op(Op op, TableNode* result, TNodeOrConst* arg);
|
||||
void emit_assignment(TableNode* target, TNodeOrConst* source);
|
||||
char* get_string(TNodeOrConst* tc);
|
||||
void emit_as_file(FILE* out_file, Instruction* i);
|
||||
void emit_label(int label);
|
||||
void emit_jump(int label);
|
||||
void emit_conditional_jump(Op condition, int label, ...);
|
||||
void emit_function_start(int name);
|
||||
void emit_parameter(TNodeOrConst* param);
|
||||
void emit_function_call(TableNode* result, int param_count, TNodeOrConst* name);
|
||||
void emit_return(TNodeOrConst* value);
|
||||
void emit_reserve(TableNode* result, TNodeOrConst* size);
|
||||
void emit_release(TableNode* pointer);
|
||||
void emit_deref_right();
|
||||
void emit_deref_left();
|
||||
void emit_field_access(char* result, char* record, char* field);
|
||||
void emit_array_access(Op op, TableNode* result, TNodeOrConst* array, TNodeOrConst* index);
|
||||
void emit_bounds_check(TNodeOrConst* index, TNodeOrConst* arr);
|
||||
char* label_gen();
|
||||
TableNode* getTN(TNodeOrConst* tnc);
|
||||
int getConst(TNodeOrConst* tnc);
|
||||
|
||||
extern int label_count;
|
||||
extern Instruction* begin;
|
||||
extern Instruction* current;
|
||||
|
||||
extern int offset;
|
||||
extern int currentsp;
|
||||
extern CGNode* cgList;
|
29
src/lexicalStructure.h
Normal file
29
src/lexicalStructure.h
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../src/symbol_table.h"
|
||||
#include "../tmp/grammar.tab.h"
|
||||
|
||||
extern SymbolTable *cur;
|
||||
extern FILE *tok_flag;
|
||||
extern TableNode *funprime;
|
||||
extern TableNode *funtypeprime;
|
||||
extern TableNode *arrayprim;
|
||||
extern TableNode *recprime;
|
||||
extern TableNode *integ;
|
||||
extern TableNode *addr;
|
||||
extern TableNode *chara;
|
||||
extern TableNode *stri;
|
||||
extern TableNode *boo;
|
||||
extern TableNode *undefined;
|
||||
extern void incr(int lnum, int cnum, int tok);
|
||||
extern void print_tok(int tok);
|
||||
|
||||
int line_number = 1;
|
||||
int column_number = 1;
|
||||
int yycolumn = 1;
|
||||
|
||||
#define YY_USER_ACTION { \
|
||||
yylloc.first_line = yylineno; \
|
||||
yylloc.last_line = yylineno; \
|
||||
yylloc.first_column = yycolumn; \
|
||||
yylloc.last_column = yycolumn + yyleng - 1; \
|
||||
yycolumn += yyleng; \
|
||||
}
|
@ -6,34 +6,7 @@
|
||||
%option yylineno
|
||||
|
||||
%{
|
||||
#include "../tmp/grammar.tab.h"
|
||||
#include "../src/symbol_table.h"
|
||||
extern SymbolTable * cur;
|
||||
extern FILE* tok_flag;
|
||||
extern TableNode *funprime;
|
||||
extern TableNode *funtypeprime;
|
||||
extern TableNode *arrayprim;
|
||||
extern TableNode *recprime;
|
||||
extern TableNode *integ;
|
||||
extern TableNode *addr;
|
||||
extern TableNode *chara;
|
||||
extern TableNode *stri;
|
||||
extern TableNode *boo;
|
||||
extern TableNode *undefined;
|
||||
extern void incr(int lnum,int cnum, int tok);
|
||||
extern void print_tok(int tok);
|
||||
|
||||
int line_number = 1;
|
||||
int column_number = 1;
|
||||
int yycolumn = 1;
|
||||
|
||||
#define YY_USER_ACTION { \
|
||||
yylloc.first_line = yylineno; \
|
||||
yylloc.last_line = yylineno; \
|
||||
yylloc.first_column = yycolumn; \
|
||||
yylloc.last_column = yycolumn + yyleng - 1; \
|
||||
yycolumn += yyleng; \
|
||||
}
|
||||
#include "../src/lexicalStructure.h"
|
||||
%}
|
||||
|
||||
STARCOM [^\*]|\*+[^\)\*]+
|
||||
|
@ -127,7 +127,6 @@ int run(FILE *alpha) {
|
||||
|
||||
fseek(alpha, 0, SEEK_SET);
|
||||
|
||||
|
||||
// print_code_lines();
|
||||
|
||||
yyin = alpha;
|
||||
@ -163,8 +162,8 @@ int run(FILE *alpha) {
|
||||
}
|
||||
|
||||
//if (cg_flag != NULL) {
|
||||
// printf("Flag -cg is not implemented yet\n");
|
||||
//fclose(cg_flag);
|
||||
// printf("Flag -cg is not implemented yet\n");
|
||||
//fclose(cg_flag);
|
||||
//}
|
||||
|
||||
if (yyin != NULL) {
|
||||
@ -271,7 +270,7 @@ void append_code_line(CodeLine *code_line) {
|
||||
void print_code_lines() {
|
||||
CodeLine *current = code_head;
|
||||
while (current != NULL) {
|
||||
printf("%d %03d: %s",current->line_number, current->line);
|
||||
printf("%d %03d: %s", current->line_number, current->line);
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
|
||||
#include "../tmp/flex.h"
|
||||
#include "../tmp/grammar.tab.h"
|
||||
#include "codegen.h"
|
||||
#include "intermediate_code.h"
|
||||
#include "symbol_table.h"
|
||||
|
||||
extern int line_number;
|
||||
@ -66,7 +68,7 @@ TableNode *boo;
|
||||
TableNode *recprime;
|
||||
TableNode *funtypeprime;
|
||||
TableNode *undefined;
|
||||
extern Instruction* begin;
|
||||
extern Instruction *begin;
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
int check_flag(char *arg, char *alpha);
|
||||
|
1034
src/symbol_table.c
1034
src/symbol_table.c
File diff suppressed because it is too large
Load Diff
@ -2,16 +2,15 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SIZE_INT 4
|
||||
#define SIZE_ADDR 8
|
||||
#define SIZE_CHAR 1
|
||||
#define SIZE_BOOL 4 //TODO: Ask Carl what this size should be
|
||||
#define SIZE_BOOL 1
|
||||
|
||||
struct TableNode;
|
||||
typedef struct TFList TFList;
|
||||
@ -63,7 +62,6 @@ typedef struct ListOfTable {
|
||||
struct ListOfTable *next;
|
||||
} ListOfTable;
|
||||
|
||||
//Table node to store
|
||||
typedef struct TableNode {
|
||||
struct TableNode *theType;
|
||||
int tag;
|
||||
@ -99,7 +97,10 @@ void printdebug_impl(char *file, int line, const char *format, ...);
|
||||
#define printdebug(format, ...) \
|
||||
printdebug_impl(__FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
|
||||
void printdebug_impl(char *file, int line, const char *format, ...);
|
||||
char *temp_var_gen();
|
||||
Constant_Stack *Push(TableNode *type, void *value, bool isConst);
|
||||
Constant_Stack *Pop();
|
||||
Constant_Stack *Print_Stack();
|
||||
AdInfo *CreatePrimitiveInfo(int size);
|
||||
int getPrimSize(TableNode *definition);
|
||||
AdInfo *CreateArrayInfo(int dim, TableNode *type);
|
||||
@ -187,189 +188,4 @@ extern char *COLOR_YELLOW;
|
||||
extern char *COLOR_LIGHTBLUE;
|
||||
extern char *COLOR_LIGHTPURPLE;
|
||||
extern char *COLOR_LIGHTCYAN;
|
||||
extern char *COLOR_WHITE;
|
||||
//_____________________________________________________________
|
||||
// these are from page 364
|
||||
typedef enum {
|
||||
E_LABEL = 10000, // this is not in the book
|
||||
E_ADD, // 1 from the list
|
||||
E_SUB, // 1
|
||||
E_MUL, // 1
|
||||
E_DIV, // 1
|
||||
E_MOD, // 1
|
||||
E_OR, // 1
|
||||
E_AND, // 1
|
||||
E_NEG, // 2
|
||||
E_NOT, // 2
|
||||
E_ASSIGN, // 3
|
||||
E_GOTO, // 4
|
||||
E_COND_GOTO, // 5 I don't thik I need this because we could just follow the < or the = and just assume that it's a cond got
|
||||
E_IF_X_TRUE, // 5
|
||||
E_IF_X_FALSE, // 5
|
||||
E_LESS_THAN, // 6 rule 1 + 5
|
||||
E_EQUAL_TO, // 6 rule 1 + 5
|
||||
E_CALL, // 7
|
||||
E_PARAM, // 7
|
||||
E_RETURN, // 7
|
||||
E_INDEX_COPY_RIGHT, // 8 this is x = y[i]
|
||||
E_INDEX_COPY_LEFT, // 8 x[i] = y
|
||||
E_ADDRESS_OF, // 9 x = &y
|
||||
E_DEREF_RIGHT, // 9 x = *y
|
||||
E_DEREF_LEFT // 9 x* = y
|
||||
} Op;
|
||||
|
||||
typedef enum {
|
||||
NODE = 11000, // TableNode
|
||||
INTEGER, // int
|
||||
STRING, // char *
|
||||
CHARACTER, // char
|
||||
ADDRESS, // void *
|
||||
BOOLEAN // bool
|
||||
} Discriminant;
|
||||
|
||||
typedef union {
|
||||
TableNode * node;
|
||||
int integer;
|
||||
char * string;
|
||||
char character;
|
||||
void * address;
|
||||
bool Boolean;
|
||||
} TNConstUnion;
|
||||
|
||||
typedef struct {
|
||||
Discriminant d;
|
||||
TNConstUnion * tnc_union;
|
||||
} TNodeOrConst;
|
||||
|
||||
|
||||
typedef struct Instruction Instruction;
|
||||
typedef struct Instruction {
|
||||
Op opcode;
|
||||
TableNode * result;
|
||||
TNodeOrConst * operand1;
|
||||
TNodeOrConst * operand2;
|
||||
int label;
|
||||
int index;
|
||||
|
||||
Instruction * prev;
|
||||
Instruction * next;
|
||||
} Instruction;
|
||||
|
||||
|
||||
typedef struct TFList {
|
||||
Instruction * i;
|
||||
TFList * next;
|
||||
} TFList;
|
||||
|
||||
TFList * make_list(Instruction * i);
|
||||
// - makelist(i) function to create instruction lists
|
||||
void merge(TFList * l1, TFList * l2);
|
||||
// - merge(p1,p2) function to concatenate lists
|
||||
void backpatch(TFList * l, int label);
|
||||
// - backpatch(p,i) function to fill in jump targets
|
||||
|
||||
|
||||
//int temp_count;
|
||||
//int label_count;
|
||||
//bool code_gen;
|
||||
//Instruction * begin;
|
||||
//Instruction * current;
|
||||
//char * temp;
|
||||
|
||||
|
||||
|
||||
TNodeOrConst * tn_or_const(Discriminant d, void * tnc);
|
||||
void emit_binary_op(Op op, TableNode * result, TNodeOrConst * arg1, TNodeOrConst * arg2);
|
||||
void emit_unary_op(Op op, TableNode * result, TNodeOrConst * arg);
|
||||
void emit_assignment(TableNode * target, TNodeOrConst * source);
|
||||
void emit_as_file(FILE * out_file, Instruction * instr_arr);
|
||||
void emit_label(int label);
|
||||
void emit_jump(int label);
|
||||
|
||||
void emit_conditional_jump(Op condition, int label, ...);
|
||||
|
||||
void emit_function_start(int name);
|
||||
void emit_parameter(TNodeOrConst * param);
|
||||
void emit_function_call(TableNode * result, int param_count, TNodeOrConst * name);
|
||||
void emit_return(TNodeOrConst * value);
|
||||
void emit_reserve(TableNode * result, TNodeOrConst * size);
|
||||
void emit_release(TableNode * pointer);
|
||||
void emit_field_access(char* result, char* record, char* field);
|
||||
void emit_array_access(Op op, TableNode * result, TNodeOrConst * array, TNodeOrConst * index);
|
||||
void emit_bounds_check(TNodeOrConst * index, TNodeOrConst * arr);
|
||||
|
||||
// * Implement instruction array storage for backpatching
|
||||
/*
|
||||
Track 2: Control Flow & Boolean Expressions
|
||||
* Implement backpatching infrastructure:
|
||||
* Create truelist and falselist attributes for Boolean expressions
|
||||
* Create control flow emission functions:
|
||||
* Add Bison actions for control structures:
|
||||
- if-then-else with backpatching
|
||||
- while loops with backpatching
|
||||
* Implement short-circuit Boolean operations (&&, ||, !)
|
||||
* Add marker (M) nonterminal for recording instruction positions
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Track 3: Functions & Complex Types
|
||||
* Implement function-related emission:
|
||||
* Add Bison actions for the 'as' clause
|
||||
* Create memory layout calculation functions:
|
||||
- calculate_record_size(Record_Type* type) → returns bytes needed
|
||||
- calculate_array_size(Array_Type* type, int dimensions[]) → returns total bytes
|
||||
- calculate_field_offset(Record_Type* type, char* field_name) → returns offset
|
||||
* Add Bison actions for arrays and records
|
||||
*/
|
||||
|
||||
/*
|
||||
Track 4: Memory Access & Integration
|
||||
* Implement array and record access code:
|
||||
- emit_field_access(char* result, char* record, char* field)
|
||||
- emit_array_access(char* result, char* array, char* index, char* dimension)
|
||||
* Add array dimension access (a._1, a._2, etc.)
|
||||
* Implement bounds checking emission:
|
||||
- emit_bounds_check(char* index, char* size, char* error_label)
|
||||
* Create the code generation driver function
|
||||
* Implement common error handling
|
||||
* Document the complete intermediate instruction set
|
||||
* Build integration test suite covering all language features
|
||||
* Implement row-major/column-major array layout calculation
|
||||
*/
|
||||
//-------------------------------------------------------------
|
||||
extern FILE *cg_flag;
|
||||
typedef struct CGNode {
|
||||
TableNode *tn;
|
||||
int address;
|
||||
CGNode *next;
|
||||
}CGNode;
|
||||
|
||||
int generate();
|
||||
CGNode *getNextCG(CGNode *cg);
|
||||
int getAddress(CGNode *cg);
|
||||
TableNode *getTNofCG(CGNode *cg);
|
||||
int generateLabel(Instruction *instruction);
|
||||
int generateAdd(Instruction *instruction);
|
||||
int generateSub(Instruction *instruction);
|
||||
int generateMult(Instruction *instruction);
|
||||
int generateDiv(Instruction *instruction);
|
||||
int generateMod(Instruction *instruction);
|
||||
int generateOr(Instruction *instruction);
|
||||
int generateAnd(Instruction *instruction);
|
||||
int generateNeg(Instruction *instruction);
|
||||
int generateNot(Instruction *instruction);
|
||||
int generateDiv(Instruction *instruction);
|
||||
int generateAssign(Instruction *instruction); // is this for something like x = 1?
|
||||
int generateGoto(Instruction *instruction);
|
||||
int generateCondGoto(Instruction *instruction);
|
||||
int generateIfTrue(Instruction *instruction);
|
||||
int generateIfFalse(Instruction *instruction);
|
||||
int generateLessThan(Instruction *instruction);
|
||||
int generateEqualTo(Instruction *instruction);
|
||||
int generateCall(Instruction *instruction);
|
||||
int generateReturn(Instruction *instruction);
|
||||
int generateCopyRight(Instruction *instruction);
|
||||
int generateCopyLeft(Instruction *instruction);
|
||||
int generateAddressOf(Instruction *instruction);
|
||||
int generateParam(Instruction *instruction);
|
||||
extern char *COLOR_WHITE;
|
Reference in New Issue
Block a user