Implement code generation for new operators.
This commit is contained in:
parent
eab4d51f25
commit
627839aa5d
|
@ -137,7 +137,8 @@ enum SyntaxOps {
|
||||||
OP_POSTDEC, // Decrement var after reference.
|
OP_POSTDEC, // Decrement var after reference.
|
||||||
|
|
||||||
OP_BITNOT, // Invert a number bitwise
|
OP_BITNOT, // Invert a number bitwise
|
||||||
OP_BOOLNOT, // Invert a statement
|
OP_BOOLNOT, // Invert a statement logically
|
||||||
|
OP_NEGATE, // Negate a number (turn a positive number negative)
|
||||||
|
|
||||||
OP_BOOLCONV, // Convert an expression to a boolean.s
|
OP_BOOLCONV, // Convert an expression to a boolean.s
|
||||||
|
|
||||||
|
@ -354,7 +355,7 @@ int AsMul(int Left, int Right);
|
||||||
int AsSub(int Left, int Right);
|
int AsSub(int Left, int Right);
|
||||||
int AsDiv(int Left, int Right);
|
int AsDiv(int Left, int Right);
|
||||||
|
|
||||||
int AsLdVar(int ID);
|
int AsLdVar(int ID, int Operation);
|
||||||
int AsStrVar(int Register, int ID);
|
int AsStrVar(int Register, int ID);
|
||||||
|
|
||||||
|
|
||||||
|
@ -375,6 +376,16 @@ int AsGreat(int Left, int Right);
|
||||||
int AsLessE(int Left, int Right);
|
int AsLessE(int Left, int Right);
|
||||||
int AsGreatE(int Left, int Right);
|
int AsGreatE(int Left, int Right);
|
||||||
|
|
||||||
|
int AsBitwiseAND(int Left, int Right);
|
||||||
|
int AsBitwiseOR(int Left, int Right);
|
||||||
|
int AsBitwiseXOR(int Left, int Right);
|
||||||
|
int AsNegate(int Register);
|
||||||
|
int AsInvert(int Register);
|
||||||
|
int AsBooleanNOT(int Register);
|
||||||
|
int AsShiftLeft(int Left, int Right);
|
||||||
|
int AsShiftRight(int Left, int Right);
|
||||||
|
int AsBooleanConvert(int Register, int Operation, int Label);
|
||||||
|
|
||||||
int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label);
|
int AsCompareJmp(int Operation, int RegisterLeft, int RegisterRight, int Label);
|
||||||
int AsCompare(int Operation, int RegisterLeft, int RegisterRight);
|
int AsCompare(int Operation, int RegisterLeft, int RegisterRight);
|
||||||
int AsIf(struct ASTNode* Node);
|
int AsIf(struct ASTNode* Node);
|
||||||
|
|
164
src/Assembler.c
164
src/Assembler.c
|
@ -160,7 +160,7 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
||||||
|
|
||||||
case REF_IDENT:
|
case REF_IDENT:
|
||||||
if(Node->RVal || ParentOp == OP_DEREF)
|
if(Node->RVal || ParentOp == OP_DEREF)
|
||||||
return AsLdVar(Node->Value.ID);
|
return AsLdVar(Node->Value.ID, Node->Operation);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -180,6 +180,45 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
||||||
return AsWhile(Node);
|
return AsWhile(Node);
|
||||||
break; */
|
break; */
|
||||||
|
|
||||||
|
case OP_BITAND:
|
||||||
|
return AsBitwiseAND(LeftVal, RightVal);
|
||||||
|
|
||||||
|
case OP_BITOR:
|
||||||
|
return AsBitwiseOR(LeftVal, RightVal);
|
||||||
|
|
||||||
|
case OP_BITXOR:
|
||||||
|
return AsBitwiseXOR(LeftVal, RightVal);
|
||||||
|
|
||||||
|
case OP_SHIFTL:
|
||||||
|
return AsShiftLeft(LeftVal, RightVal);
|
||||||
|
|
||||||
|
case OP_SHIFTR:
|
||||||
|
return AsShiftRight(LeftVal, RightVal);
|
||||||
|
|
||||||
|
case OP_POSTINC:
|
||||||
|
return AsLdVar(Node->Value.IntValue, Node->Operation);
|
||||||
|
|
||||||
|
case OP_POSTDEC:
|
||||||
|
return AsLdVar(Node->Value.IntValue, Node->Operation);
|
||||||
|
|
||||||
|
case OP_PREINC:
|
||||||
|
return AsLdVar(Node->Value.IntValue, Node->Operation);
|
||||||
|
|
||||||
|
case OP_PREDEC:
|
||||||
|
return AsLdVar(Node->Value.IntValue, Node->Operation);
|
||||||
|
|
||||||
|
case OP_BOOLNOT:
|
||||||
|
return AsBooleanNOT(LeftVal);
|
||||||
|
|
||||||
|
case OP_BITNOT:
|
||||||
|
return AsInvert(LeftVal);
|
||||||
|
|
||||||
|
case OP_NEGATE:
|
||||||
|
return AsNegate(LeftVal);
|
||||||
|
|
||||||
|
case OP_BOOLCONV:
|
||||||
|
return AsBooleanConvert(LeftVal, ParentOp, Register);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DieDecimal("Unknown ASM Operation", Node->Operation);
|
DieDecimal("Unknown ASM Operation", Node->Operation);
|
||||||
}
|
}
|
||||||
|
@ -397,27 +436,70 @@ int AsShl(int Register, int Val) {
|
||||||
return Register;
|
return Register;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsLdVar(int ID) {
|
int AsLdVar(int ID, int Operation) {
|
||||||
int Reg = RetrieveRegister();
|
int Reg = RetrieveRegister();
|
||||||
|
|
||||||
printf("\tStoring %s's contents into %s\n", Symbols[ID].Name, Registers[Reg]);
|
printf("\tStoring %s's contents into %s\n", Symbols[ID].Name, Registers[Reg]);
|
||||||
|
|
||||||
switch(Symbols[ID].Type) {
|
switch(Symbols[ID].Type) {
|
||||||
case RET_CHAR:
|
case RET_CHAR:
|
||||||
// movzbq zeroes, then moves a byte into the quad register
|
switch(Operation) {
|
||||||
fprintf(OutputFile, "\tmovb\t%s(\%%rip), %s\n", Symbols[ID].Name, ByteRegisters[Reg]);
|
case OP_PREINC:
|
||||||
|
fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
case OP_PREDEC:
|
||||||
|
fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(OutputFile, "\tmovzbq\t%s(\%%rip), %s\n", Symbols[ID].Name, Registers[Reg]);
|
||||||
|
|
||||||
|
switch(Operation) {
|
||||||
|
case OP_POSTINC:
|
||||||
|
fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
case OP_POSTDEC:
|
||||||
|
fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RET_INT:
|
case RET_INT:
|
||||||
fprintf(OutputFile, "\tmovl\t%s(\%%rip), %s\n", Symbols[ID].Name, DoubleRegisters[Reg]);
|
switch(Operation) {
|
||||||
break;
|
case OP_PREINC:
|
||||||
|
fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
case OP_PREDEC:
|
||||||
|
fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(OutputFile, "\tmovslq\t%s(\%%rip), %s\n", Symbols[ID].Name, Registers[Reg]);
|
||||||
|
|
||||||
|
switch(Operation) {
|
||||||
|
case OP_POSTINC:
|
||||||
|
fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
case OP_POSTDEC:
|
||||||
|
fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
case RET_LONG:
|
case RET_LONG:
|
||||||
case PTR_CHAR:
|
case PTR_CHAR:
|
||||||
case PTR_INT:
|
case PTR_INT:
|
||||||
case PTR_LONG:
|
case PTR_LONG:
|
||||||
case PTR_VOID:
|
case PTR_VOID:
|
||||||
fprintf(OutputFile, "\tmovq\t%s(%%rip), %s\n", Symbols[ID].Name, Registers[Reg]);
|
switch(Operation) {
|
||||||
|
case OP_PREINC:
|
||||||
|
fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
case OP_PREDEC:
|
||||||
|
fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(OutputFile, "\tmovq\t%s(\%%rip), %s\n", Symbols[ID].Name, Registers[Reg]);
|
||||||
|
|
||||||
|
switch(Operation) {
|
||||||
|
case OP_POSTINC:
|
||||||
|
fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
case OP_POSTDEC:
|
||||||
|
fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Symbols[ID].Name); break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -601,6 +683,72 @@ void AssemblerPrint(int Register) {
|
||||||
DeallocateRegister(Register);
|
DeallocateRegister(Register);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AsBitwiseAND(int Left, int Right) {
|
||||||
|
fprintf(OutputFile, "\tandq\t%s, %s\n", Registers[Left], Registers[Right]);
|
||||||
|
DeallocateRegister(Left);
|
||||||
|
return Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsBitwiseOR(int Left, int Right) {
|
||||||
|
fprintf(OutputFile, "\torq\t%s, %s\n", Registers[Left], Registers[Right]);
|
||||||
|
DeallocateRegister(Left);
|
||||||
|
return Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsBitwiseXOR(int Left, int Right) {
|
||||||
|
fprintf(OutputFile, "\txorq\t%s, %s\n", Registers[Left], Registers[Right]);
|
||||||
|
DeallocateRegister(Left);
|
||||||
|
return Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsNegate(int Register) {
|
||||||
|
fprintf(OutputFile, "\tnegq\t%s\n", Registers[Register]);
|
||||||
|
return Register;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsInvert(int Register) {
|
||||||
|
fprintf(OutputFile, "\tnotq\t%s\n", Registers[Register]);
|
||||||
|
return Register;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsBooleanNOT(int Register) {
|
||||||
|
fprintf(OutputFile, "\ttest\t%s, %s\n", Registers[Register], Registers[Register]);
|
||||||
|
fprintf(OutputFile, "\tsete\t%s\n", ByteRegisters[Register]);
|
||||||
|
fprintf(OutputFile, "\tmovzbq\t%s, %s\n", ByteRegisters[Register], Registers[Register]);
|
||||||
|
return Register;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsShiftLeft(int Left, int Right) {
|
||||||
|
fprintf(OutputFile, "\tmovb\t%s, \%%cl\n", ByteRegisters[Right]);
|
||||||
|
fprintf(OutputFile, "\tshlq\t\%%cl, %s\n", Registers[Left]);
|
||||||
|
DeallocateRegister(Right);
|
||||||
|
return Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsShiftRight(int Left, int Right) {
|
||||||
|
fprintf(OutputFile, "\tmovb\t%s, \%%cl\n", ByteRegisters[Right]);
|
||||||
|
fprintf(OutputFile, "\tshrq\t\%%cl, %s\n", Registers[Left]);
|
||||||
|
DeallocateRegister(Right);
|
||||||
|
return Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AsBooleanConvert(int Register, int Operation, int Label) {
|
||||||
|
fprintf(OutputFile, "\ttest\t%s, %s\n", Registers[Register], Registers[Register]);
|
||||||
|
|
||||||
|
switch(Operation) {
|
||||||
|
case OP_IF:
|
||||||
|
case OP_LOOP:
|
||||||
|
fprintf(OutputFile, "\tje\tL%d\n", Label);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(OutputFile, "\tsetnz\t%s\n", ByteRegisters[Register]);
|
||||||
|
fprintf(OutputFile, "\tmovzbq\t%s, %s\n", ByteRegisters[Register], Registers[Register]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Register;
|
||||||
|
}
|
||||||
|
|
||||||
void AssemblerPreamble() {
|
void AssemblerPreamble() {
|
||||||
DeallocateAllRegisters();
|
DeallocateAllRegisters();
|
||||||
fputs(
|
fputs(
|
||||||
|
|
22
src/Dump.c
22
src/Dump.c
|
@ -89,7 +89,27 @@ void DumpTree(struct ASTNode* node, int level) {
|
||||||
case OP_DEREF:
|
case OP_DEREF:
|
||||||
fprintf(stdout, "OP_DEREF %s\n", node->RVal ? "rval" : ""); return;
|
fprintf(stdout, "OP_DEREF %s\n", node->RVal ? "rval" : ""); return;
|
||||||
case OP_SCALE: fprintf(stdout, "OP_SCALE %s\n", TypeNames[node->Value.Size]); return;
|
case OP_SCALE: fprintf(stdout, "OP_SCALE %s\n", TypeNames[node->Value.Size]); return;
|
||||||
|
|
||||||
|
case OP_BOOLOR: fprintf(stdout, "OP_BOOLOR\n"); return;
|
||||||
|
case OP_BOOLAND: fprintf(stdout, "OP_BOOLAND\n"); return;
|
||||||
|
case OP_BITOR: fprintf(stdout, "OP_BITOR\n"); return;
|
||||||
|
case OP_BITXOR: fprintf(stdout, "OP_BITXOR\n"); return;
|
||||||
|
case OP_BITAND: fprintf(stdout, "OP_BITAND\n"); return;
|
||||||
|
|
||||||
|
case OP_SHIFTL: fprintf(stdout, "OP_SHIFTL\n"); return;
|
||||||
|
case OP_SHIFTR: fprintf(stdout, "OP_SHIFTR\n"); return;
|
||||||
|
|
||||||
|
case OP_PREINC: fprintf(stdout, "OP_PREINC\n"); return;
|
||||||
|
case OP_PREDEC: fprintf(stdout, "OP_PREDEC\n"); return;
|
||||||
|
case OP_POSTINC: fprintf(stdout, "OP_POSTINC\n"); return;
|
||||||
|
case OP_POSTDEC: fprintf(stdout, "OP_POSTDEC\n"); return;
|
||||||
|
|
||||||
|
case OP_BITNOT: fprintf(stdout, "OP_BITNOT\n"); return;
|
||||||
|
case OP_BOOLNOT: fprintf(stdout, "OP_BOOLNOT\n"); return;
|
||||||
|
case OP_NEGATE: fprintf(stdout, "OP_NEGATE\n"); return;
|
||||||
|
|
||||||
|
case OP_BOOLCONV: fprintf(stdout, "OP_BOOLCONV\n"); return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DieDecimal("Unknown Dump Operator", node->Operation);
|
DieDecimal("Unknown Dump Operator", node->Operation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,11 @@ char* TokenNames[] = {
|
||||||
"Multiplication",
|
"Multiplication",
|
||||||
"Division",
|
"Division",
|
||||||
|
|
||||||
|
"Increment",
|
||||||
|
"Decrement",
|
||||||
|
|
||||||
|
"Statement Logical Invert",
|
||||||
|
"Bitwise Invert",
|
||||||
|
|
||||||
"Integer literal",
|
"Integer literal",
|
||||||
"Statement End",
|
"Statement End",
|
||||||
|
@ -93,6 +98,7 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
AddFunctionSymbol("PrintInteger", RET_CHAR, ST_FUNC, 0, 1);
|
AddFunctionSymbol("PrintInteger", RET_CHAR, ST_FUNC, 0, 1);
|
||||||
AddFunctionSymbol("PrintString", RET_CHAR, ST_FUNC, 1, 1);
|
AddFunctionSymbol("PrintString", RET_CHAR, ST_FUNC, 1, 1);
|
||||||
|
AddFunctionSymbol("PrintChar", RET_CHAR, ST_FUNC, 2, 1);
|
||||||
//AddSymbol("forgecord", PTR_CHAR, ST_VAR);
|
//AddSymbol("forgecord", PTR_CHAR, ST_VAR);
|
||||||
|
|
||||||
Tokenise(&CurrentToken);
|
Tokenise(&CurrentToken);
|
||||||
|
|
|
@ -58,7 +58,7 @@ void BeginVariableDeclaration(int Type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DieDecimal("\nExpected ; after identifier, found", CurrentToken.type);
|
DieMessage("\nExpected ; after identifier, found", TokenNames[CurrentToken.type]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ struct ASTNode* IfStatement() {
|
||||||
// No null checking, no arithmetic, no functions.
|
// No null checking, no arithmetic, no functions.
|
||||||
// TODO: this
|
// TODO: this
|
||||||
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
|
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
|
||||||
Die("Invalid Comparison in if statement");
|
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0);
|
||||||
|
|
||||||
VerifyToken(LI_RPARE, ")");
|
VerifyToken(LI_RPARE, ")");
|
||||||
|
|
||||||
|
@ -259,7 +259,7 @@ struct ASTNode* ForStatement() {
|
||||||
|
|
||||||
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
|
if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE)
|
||||||
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0);
|
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0);
|
||||||
|
|
||||||
VerifyToken(LI_SEMIC, ";");
|
VerifyToken(LI_SEMIC, ";");
|
||||||
|
|
||||||
Postop = ParseStatement();
|
Postop = ParseStatement();
|
||||||
|
@ -364,6 +364,13 @@ struct ASTNode* PrefixStatement() {
|
||||||
Tree->RVal = 1;
|
Tree->RVal = 1;
|
||||||
Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, 0);
|
Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AR_MINUS:
|
||||||
|
Tokenise(&CurrentToken);
|
||||||
|
Tree = PrefixStatement();
|
||||||
|
|
||||||
|
Tree = ConstructASTBranch(OP_NEGATE, Tree->ExprType, Tree, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case PPMM_PLUS:
|
case PPMM_PLUS:
|
||||||
Tokenise(&CurrentToken);
|
Tokenise(&CurrentToken);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user