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_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
|
||||
|
||||
|
@ -354,7 +355,7 @@ int AsMul(int Left, int Right);
|
|||
int AsSub(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);
|
||||
|
||||
|
||||
|
@ -375,6 +376,16 @@ int AsGreat(int Left, int Right);
|
|||
int AsLessE(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 AsCompare(int Operation, int RegisterLeft, int RegisterRight);
|
||||
int AsIf(struct ASTNode* Node);
|
||||
|
|
162
src/Assembler.c
162
src/Assembler.c
|
@ -160,7 +160,7 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
|||
|
||||
case REF_IDENT:
|
||||
if(Node->RVal || ParentOp == OP_DEREF)
|
||||
return AsLdVar(Node->Value.ID);
|
||||
return AsLdVar(Node->Value.ID, Node->Operation);
|
||||
else
|
||||
return -1;
|
||||
|
||||
|
@ -180,6 +180,45 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
|
|||
return AsWhile(Node);
|
||||
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:
|
||||
DieDecimal("Unknown ASM Operation", Node->Operation);
|
||||
}
|
||||
|
@ -397,27 +436,70 @@ int AsShl(int Register, int Val) {
|
|||
return Register;
|
||||
}
|
||||
|
||||
int AsLdVar(int ID) {
|
||||
int AsLdVar(int ID, int Operation) {
|
||||
int Reg = RetrieveRegister();
|
||||
|
||||
printf("\tStoring %s's contents into %s\n", Symbols[ID].Name, Registers[Reg]);
|
||||
|
||||
switch(Symbols[ID].Type) {
|
||||
case RET_CHAR:
|
||||
// movzbq zeroes, then moves a byte into the quad register
|
||||
fprintf(OutputFile, "\tmovb\t%s(\%%rip), %s\n", Symbols[ID].Name, ByteRegisters[Reg]);
|
||||
switch(Operation) {
|
||||
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;
|
||||
|
||||
case RET_INT:
|
||||
fprintf(OutputFile, "\tmovl\t%s(\%%rip), %s\n", Symbols[ID].Name, DoubleRegisters[Reg]);
|
||||
break;
|
||||
switch(Operation) {
|
||||
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 PTR_CHAR:
|
||||
case PTR_INT:
|
||||
case PTR_LONG:
|
||||
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;
|
||||
|
||||
default:
|
||||
|
@ -601,6 +683,72 @@ void AssemblerPrint(int 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() {
|
||||
DeallocateAllRegisters();
|
||||
fputs(
|
||||
|
|
20
src/Dump.c
20
src/Dump.c
|
@ -90,6 +90,26 @@ void DumpTree(struct ASTNode* node, int level) {
|
|||
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_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:
|
||||
DieDecimal("Unknown Dump Operator", node->Operation);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,11 @@ char* TokenNames[] = {
|
|||
"Multiplication",
|
||||
"Division",
|
||||
|
||||
"Increment",
|
||||
"Decrement",
|
||||
|
||||
"Statement Logical Invert",
|
||||
"Bitwise Invert",
|
||||
|
||||
"Integer literal",
|
||||
"Statement End",
|
||||
|
@ -93,6 +98,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
AddFunctionSymbol("PrintInteger", RET_CHAR, ST_FUNC, 0, 1);
|
||||
AddFunctionSymbol("PrintString", RET_CHAR, ST_FUNC, 1, 1);
|
||||
AddFunctionSymbol("PrintChar", RET_CHAR, ST_FUNC, 2, 1);
|
||||
//AddSymbol("forgecord", PTR_CHAR, ST_VAR);
|
||||
|
||||
Tokenise(&CurrentToken);
|
||||
|
|
|
@ -58,7 +58,7 @@ void BeginVariableDeclaration(int Type) {
|
|||
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.
|
||||
// TODO: this
|
||||
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, ")");
|
||||
|
||||
|
@ -365,6 +365,13 @@ struct ASTNode* PrefixStatement() {
|
|||
Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, 0);
|
||||
break;
|
||||
|
||||
case AR_MINUS:
|
||||
Tokenise(&CurrentToken);
|
||||
Tree = PrefixStatement();
|
||||
|
||||
Tree = ConstructASTBranch(OP_NEGATE, Tree->ExprType, Tree, 0);
|
||||
break;
|
||||
|
||||
case PPMM_PLUS:
|
||||
Tokenise(&CurrentToken);
|
||||
Tree = PrefixStatement();
|
||||
|
|
Loading…
Reference in New Issue
Block a user