Implement code generation for new operators.

This commit is contained in:
Curle 2020-11-24 13:17:01 +00:00
parent eab4d51f25
commit 627839aa5d
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
5 changed files with 206 additions and 14 deletions

View File

@ -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);

View File

@ -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(

View File

@ -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);
} }

View File

@ -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);

View File

@ -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);