diff --git a/include/Defs.h b/include/Defs.h index 4052a51..122a387 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -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); diff --git a/src/Assembler.c b/src/Assembler.c index c1b391c..848543a 100644 --- a/src/Assembler.c +++ b/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( diff --git a/src/Dump.c b/src/Dump.c index 8bf25d8..4225af6 100644 --- a/src/Dump.c +++ b/src/Dump.c @@ -89,7 +89,27 @@ void DumpTree(struct ASTNode* node, int level) { case OP_DEREF: 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); } diff --git a/src/Main.c b/src/Main.c index 2296a24..87c14fb 100644 --- a/src/Main.c +++ b/src/Main.c @@ -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); diff --git a/src/Statements.c b/src/Statements.c index 32a7de9..ae03c0e 100644 --- a/src/Statements.c +++ b/src/Statements.c @@ -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, ")"); @@ -259,7 +259,7 @@ struct ASTNode* ForStatement() { if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0); - + VerifyToken(LI_SEMIC, ";"); Postop = ParseStatement(); @@ -364,6 +364,13 @@ struct ASTNode* PrefixStatement() { Tree->RVal = 1; 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);