From eb118db872c7c08b7d7063586aa9703ef6a2f5a0 Mon Sep 17 00:00:00 2001 From: Curle Date: Wed, 20 Jan 2021 01:05:41 +0000 Subject: [PATCH] Major rewrite of the symbol parsing Moved from a static double-ended list to individual singly-linked lists for easier and faster parsing --- include/Data.h | 8 +- include/Defs.h | 90 +++++++++------ src/Assembler.c | 280 +++++++++++++++++++++++------------------------ src/Dump.c | 52 ++++----- src/Main.c | 5 +- src/Parser.c | 43 ++++---- src/Pointers.c | 66 +++++------ src/Statements.c | 154 ++++++++++++++------------ src/Symbols.c | 204 +++++++++++++++++++++------------- src/Types.c | 40 +++++-- 10 files changed, 510 insertions(+), 432 deletions(-) diff --git a/include/Data.h b/include/Data.h index 162a2c1..04dcd84 100644 --- a/include/Data.h +++ b/include/Data.h @@ -15,7 +15,9 @@ #define TEXTLEN 512 #define SYMBOLS 1024 -extern_ struct SymbolTable Symbols[SYMBOLS]; +extern_ struct SymbolTableEntry* Globals, *GlobalsEnd; +extern_ struct SymbolTableEntry* Locals, *LocalsEnd; +extern_ struct SymbolTableEntry* Params, *ParamsEnd; extern_ bool OptDumpTree; extern_ bool OptKeepAssembly; @@ -26,12 +28,12 @@ extern_ bool OptVerboseOutput; extern_ char* OutputFileName; extern_ char* CurrentASMFile, *CurrentObjectFile; -extern_ int TypeSizes[9]; -extern_ char* TypeNames[9]; +extern_ int TypeSizes[5]; extern_ char* TokenNames[]; extern_ int CurrentFunction; +extern_ struct SymbolTableEntry* FunctionEntry; extern_ int Line; extern_ int Overread; diff --git a/include/Defs.h b/include/Defs.h index d833323..970ddcf 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -174,11 +174,12 @@ struct ASTNode { struct ASTNode* Left; struct ASTNode* Middle; struct ASTNode* Right; + struct SymbolTableEntry* Symbol; union { int Size; // OP_SCALE's linear representation int IntValue; // TERM_INTLIT's Value int ID; // LV_IDENT's Symbols[] index. - } Value; + }; }; struct Token { @@ -191,14 +192,25 @@ struct Token { * assorted goodies. */ -struct SymbolTable { +struct SymbolTableEntry { char* Name; int Type; // An entry in DataTypes, referring to the type of this data + struct SymbolTableEntry* CompositeType; // A pointer to the start of a Symbol Table list that represents a certain Composite type int Structure; // An entry in StructureType - metadata on how to process the data - int EndLabel; // The number of the label to jump to, in order to exit this function (if applicable) - int Length; // The length of the symbol in units of 1 element -- the size of an array, for example. int Storage; // The scope of this symbol - decides when it is discarded. - int SinkOffset; // How many times must we sink the rbp to get to this symbol in the stack? + union { + int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable) + int Length; // For an array - The length of the symbol in units of 1 element -- the size of an array, for example. + int IntValue; // For an enum - The value of an Enum entry + }; + + union { + int SinkOffset; // For a variable - How many times must we sink the rbp to get to this symbol in the stack? + int Elements; // For a function - How many parameters? + }; + + struct SymbolTableEntry* NextSymbol; // The next symbol in a list + struct SymbolTableEntry* Start; // The first member in a list }; enum StorageScope { @@ -212,22 +224,23 @@ enum StorageScope { /* - * The primitive data types for the language - * //TODO: Move back into TokenTypes + * The types of data being held in memory. + * The lowest 4 bits of these enum values + * encode a nested pointer type. + * + * This meaning, a single enum can hold + * ****************int types. + * Should be enough for everyone, right? */ enum DataTypes { - RET_NONE, // No return type. Literal void. - RET_CHAR, // "char" type keyword - RET_INT, // "int" type keyword - RET_LONG, // "long" type keyword - RET_VOID, // "void" type keyword - - // Pointer types - PTR_CHAR, - PTR_INT, - PTR_LONG, - PTR_VOID, - + RET_NONE, // No return type. Literal void. + RET_CHAR = 16, // "char" type keyword + RET_INT = 32, // "int" type keyword + RET_LONG = 48, // "long" type keyword + RET_VOID = 64, // "void" type keyword + + DAT_STRUCT = 80, // Struct Data + DAT_UNION, // Union Data }; /* @@ -278,6 +291,8 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation); int TypeIsInt(int Type); int TypeIsPtr(int Type); +char* TypeNames(int Type); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * S Y N T A X T R E E * * * * * * @@ -288,11 +303,12 @@ struct ASTNode* ConstructASTNode(int Operation, int Type, struct ASTNode* Left, struct ASTNode* Middle, struct ASTNode* Right, + struct SymbolTableEntry* Symbol, int IntValue); -struct ASTNode* ConstructASTLeaf(int Operation, int Type, int IntValue); +struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue); -struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, int IntValue); +struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -336,11 +352,17 @@ struct ASTNode* PrintStatement(void); * * * * * * S Y M B O L T A B L E * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -int FindSymbol(char* Symbol); +struct SymbolTableEntry* FindSymbol(char* Symbol); +struct SymbolTableEntry* FindLocal(char* Symbol); +struct SymbolTableEntry* FindGlobal(char* Symbol); -int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length); +void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node); void FreeLocals(); +void ClearTables(); + +struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * C O N T R O L S T A T U S * * * * @@ -375,19 +397,19 @@ int AsMul(int Left, int Right); int AsSub(int Left, int Right); int AsDiv(int Left, int Right); -int AsLdGlobalVar(int ID, int Operation); -int AsLdLocalVar(int ID, int Operation); -int AsStrGlobalVar(int Register, int ID); -int AsStrLocalVar(int Register, int ID); +int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation); +int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation); +int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register); +int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register); int AsCalcOffset(int Type); void AsNewStackFrame(); int AsDeref(int Reg, int Type); int AsStrDeref(int Register1, int Register2, int Type); -int AsAddr(int ID); +int AsAddr(struct SymbolTableEntry* Entry); -void AsGlobalSymbol(int ID); +void AsGlobalSymbol(struct SymbolTableEntry* Entry); int AsNewString(char* Value); @@ -420,25 +442,25 @@ void AsLabel(int Label); int AsShl(int Register, int Val); -int AsReturn(int Register, int FuncID); +int AsReturn(struct SymbolTableEntry* Entry, int Register); int AsCallWrapper(struct ASTNode* Node); void AsCopyArgs(int Register, int Position); -int AsCall(int Register, int FuncID); +int AsCall(struct SymbolTableEntry* Entry, int Args); int AsWhile(struct ASTNode* Node); void AssemblerPrint(int Register); void AssemblerPreamble(); -void AsFunctionPreamble(int ID); -void AsFunctionEpilogue(int ID); +void AsFunctionPreamble(struct SymbolTableEntry* Entry); +void AsFunctionEpilogue(struct SymbolTableEntry* Entry); /* * * * * * * * * * * * * * * * * * * * * * * * * * * D E C L A R A T I O N * * * * * * * * * * * * * * * * * * * * * * * * * * */ -void BeginVariableDeclaration(int Type, int Scope); +struct SymbolTableEntry* BeginVariableDeclaration(int Type, int Scope); struct ASTNode* ParseIdentifier(void); struct ASTNode* IfStatement(); diff --git a/src/Assembler.c b/src/Assembler.c index 3504578..4c27d39 100644 --- a/src/Assembler.c +++ b/src/Assembler.c @@ -70,9 +70,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { return (AsCallWrapper(Node)); case OP_FUNC: - AsFunctionPreamble(Node->Value.ID); + AsFunctionPreamble(Node->Symbol); AssembleTree(Node->Left, -1, Node->Operation); - AsFunctionEpilogue(Node->Value.ID); + AsFunctionEpilogue(Node->Symbol); return -1; } @@ -107,17 +107,17 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { case OP_SCALE: // We can (ab)use the powers of 2 to do // efficient scaling with bitshifting. - switch(Node->Value.Size) { + switch(Node->Size) { case 2: return AsShl(LeftVal, 1); case 4: return AsShl(LeftVal, 2); case 8: return AsShl(LeftVal, 3); default: - RightVal = AsLoad(Node->Value.Size); + RightVal = AsLoad(Node->Size); return AsMul(LeftVal, RightVal); } case OP_ADDRESS: - return AsAddr(Node->Value.ID); + return AsAddr(Node->Symbol); case OP_DEREF: return Node->RVal ? AsDeref(LeftVal, Node->Left->ExprType) : LeftVal; @@ -127,13 +127,13 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { if(Node->Right == NULL) Die("Fault in assigning a null rvalue"); - printf("\tCalculating assignment for target %s:%d\r\n", Symbols[Node->Right->Value.ID].Name, Node->Right->Value.ID); + printf("\tCalculating assignment for target %s:\r\n", Node->Right->Symbol->Name); switch(Node->Right->Operation) { case REF_IDENT: - if(Symbols[Node->Right->Value.ID].Storage == SC_LOCAL) - return AsStrLocalVar(LeftVal, Node->Right->Value.ID); + if(Node->Right->Symbol->Storage == SC_LOCAL) + return AsStrLocalVar(Node->Right->Symbol, LeftVal); else - return AsStrGlobalVar(LeftVal, Node->Right->Value.ID); + return AsStrGlobalVar(Node->Right->Symbol, LeftVal); case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType); default: DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation); @@ -144,8 +144,8 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { return LeftVal; //AsWiden(LeftVal, Node->Left->ExprType, Node->ExprType); case OP_RET: - printf("\tReturning from %s, %d\n", Symbols[Node->Value.ID].Name, Node->Value.ID); - AsReturn(LeftVal, CurrentFunction); + printf("\tReturning from %s\n", Node->Symbol->Name); + AsReturn(FunctionEntry, LeftVal); return -1; /* case OP_EQUAL: @@ -181,18 +181,18 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { case REF_IDENT: //printf("\tReferencing variable %s %s with type %s and storage %d\r\n", Symbols[Node->Value.ID].Name, Node->RVal ? " rval " : "", ParentOp, Symbols[Node->Value.ID].Storage); if(Node->RVal || ParentOp == OP_DEREF) { - if(Symbols[Node->Value.ID].Storage == SC_LOCAL || Symbols[Node->Value.ID].Storage == SC_PARAM) - return AsLdLocalVar(Node->Value.ID, Node->Operation); + if(Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM) + return AsLdLocalVar(Node->Symbol, Node->Operation); else - return AsLdGlobalVar(Node->Value.ID, Node->Operation); + return AsLdGlobalVar(Node->Symbol, Node->Operation); } else return -1; case TERM_INTLITERAL: - return AsLoad(Node->Value.IntValue); + return AsLoad(Node->IntValue); case TERM_STRLITERAL: - return AsLoadString(Node->Value.ID); + return AsLoadString(Node->IntValue); case OP_PRINT: AssemblerPrint(LeftVal); @@ -220,16 +220,16 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { return AsShiftRight(LeftVal, RightVal); case OP_POSTINC: - return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Symbol, Node->Operation); case OP_POSTDEC: - return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Symbol, Node->Operation); case OP_PREINC: - return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Symbol, Node->Operation); case OP_PREDEC: - return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Symbol, Node->Operation); case OP_BOOLNOT: return AsBooleanNOT(LeftVal); @@ -473,225 +473,217 @@ int AsShl(int Register, int Val) { return Register; } -int AsLdGlobalVar(int ID, int Operation) { +int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation) { int Reg = RetrieveRegister(); - printf("\tStoring %s's contents into %s, globally\n", Symbols[ID].Name, Registers[Reg]); + printf("\tStoring %s's contents into %s, globally\n", Entry->Name, Registers[Reg]); - switch(Symbols[ID].Type) { - case RET_CHAR: + int TypeSize = PrimitiveSize(Entry->Type); + switch(TypeSize) { + case 1: switch(Operation) { case OP_PREINC: - fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Entry->Name); break; case OP_PREDEC: - fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name); break; } - fprintf(OutputFile, "\tmovzbq\t%s(\%%rip), %s\n", Symbols[ID].Name, Registers[Reg]); + fprintf(OutputFile, "\tmovzbq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]); switch(Operation) { case OP_POSTINC: - fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tincb\t%s(\%%rip)\n", Entry->Name); break; case OP_POSTDEC: - fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tdecb\t%s(\%%rip)\n", Entry->Name); break; } break; - case RET_INT: + case 4: switch(Operation) { case OP_PREINC: - fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Entry->Name); break; case OP_PREDEC: - fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name); break; } - fprintf(OutputFile, "\tmovslq\t%s(\%%rip), %s\n", Symbols[ID].Name, Registers[Reg]); + fprintf(OutputFile, "\tmovslq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]); switch(Operation) { case OP_POSTINC: - fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tincl\t%s(\%%rip)\n", Entry->Name); break; case OP_POSTDEC: - fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tdecl\t%s(\%%rip)\n", Entry->Name); break; } break; - case RET_LONG: - case PTR_CHAR: - case PTR_INT: - case PTR_LONG: - case PTR_VOID: + case 8: switch(Operation) { case OP_PREINC: - fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Entry->Name); break; case OP_PREDEC: - fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name); break; } - fprintf(OutputFile, "\tmovq\t%s(\%%rip), %s\n", Symbols[ID].Name, Registers[Reg]); + fprintf(OutputFile, "\tmovq\t%s(\%%rip), %s\n", Entry->Name, Registers[Reg]); switch(Operation) { case OP_POSTINC: - fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tincq\t%s(\%%rip)\n", Entry->Name); break; case OP_POSTDEC: - fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Symbols[ID].Name); break; + fprintf(OutputFile, "\tdecq\t%s(\%%rip)\n", Entry->Name); break; } break; default: - DieMessage("Bad type for loading", TypeNames[Symbols[ID].Type]); + DieMessage("Bad type for loading", TypeNames(Entry->Type)); } return Reg; } -int AsStrGlobalVar(int Register, int ID) { - printf("\tStoring contents of %s into %s, type %d, globally: ID %d\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type, ID); +int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register) { + printf("\tStoring contents of %s into %s, type %d, globally:\n", Registers[Register], Entry->Name, Entry->Type); - switch(Symbols[ID].Type) { - case RET_CHAR: + int TypeSize = PrimitiveSize(Entry->Type); + switch(TypeSize) { + case 1: // movzbq zeroes, then moves a byte into the quad register - fprintf(OutputFile, "\tmovb\t%s, %s(\%%rip)\n", ByteRegisters[Register], Symbols[ID].Name); + fprintf(OutputFile, "\tmovb\t%s, %s(\%%rip)\n", ByteRegisters[Register], Entry->Name); break; - case RET_INT: - fprintf(OutputFile, "\tmovl\t%s, %s(\%%rip)\n", DoubleRegisters[Register], Symbols[ID].Name); + case 4: + fprintf(OutputFile, "\tmovl\t%s, %s(\%%rip)\n", DoubleRegisters[Register], Entry->Name); break; - case RET_LONG: - case PTR_CHAR: - case PTR_INT: - case PTR_LONG: - case PTR_VOID: - fprintf(OutputFile, "\tmovq\t%s, %s(%%rip)\n", Registers[Register], Symbols[ID].Name); + case 8: + fprintf(OutputFile, "\tmovq\t%s, %s(%%rip)\n", Registers[Register], Entry->Name); break; default: - DieMessage("Bad type for saving", TypeNames[Symbols[ID].Type]); + DieMessage("Bad type for saving", TypeNames(Entry->Type)); } return Register; } -int AsLdLocalVar(int ID, int Operation) { +int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation) { int Reg = RetrieveRegister(); - printf("\tStoring the var at %d's contents into %s, locally\n", Symbols[ID].SinkOffset, Registers[Reg]); - - switch(Symbols[ID].Type) { - case RET_CHAR: + printf("\tStoring the var at %d's contents into %s, locally\n", Entry->SinkOffset, Registers[Reg]); + + int TypeSize = PrimitiveSize(Entry->Type); + switch(TypeSize) { + case 1: switch(Operation) { case OP_PREINC: - fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Entry->SinkOffset); break; case OP_PREDEC: - fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset); break; } - fprintf(OutputFile, "\tmovzbq\t%d(\%%rbp), %s\n", Symbols[ID].SinkOffset, Registers[Reg]); + fprintf(OutputFile, "\tmovzbq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]); switch(Operation) { case OP_POSTINC: - fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tincb\t%d(\%%rbp)\n", Entry->SinkOffset); break; case OP_POSTDEC: - fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tdecb\t%d(\%%rbp)\n", Entry->SinkOffset); break; } break; - case RET_INT: + case 4: switch(Operation) { case OP_PREINC: - fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Entry->SinkOffset); break; case OP_PREDEC: - fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset); break; } - fprintf(OutputFile, "\tmovslq\t%d(\%%rbp), %s\n", Symbols[ID].SinkOffset, Registers[Reg]); + fprintf(OutputFile, "\tmovslq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]); switch(Operation) { case OP_POSTINC: - fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tincl\t%d(\%%rbp)\n", Entry->SinkOffset); break; case OP_POSTDEC: - fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tdecl\t%d(\%%rbp)\n", Entry->SinkOffset); break; } break; - case RET_LONG: - case PTR_CHAR: - case PTR_INT: - case PTR_LONG: - case PTR_VOID: + case 8: switch(Operation) { case OP_PREINC: - fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Entry->SinkOffset); break; case OP_PREDEC: - fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset); break; } - fprintf(OutputFile, "\tmovq\t%d(\%%rbp), %s\n", Symbols[ID].SinkOffset, Registers[Reg]); + fprintf(OutputFile, "\tmovq\t%d(\%%rbp), %s\n", Entry->SinkOffset, Registers[Reg]); switch(Operation) { case OP_POSTINC: - fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tincq\t%d(\%%rbp)\n", Entry->SinkOffset); break; case OP_POSTDEC: - fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Symbols[ID].SinkOffset); break; + fprintf(OutputFile, "\tdecq\t%d(\%%rbp)\n", Entry->SinkOffset); break; } break; default: - DieMessage("Bad type for loading", TypeNames[Symbols[ID].Type]); + DieMessage("Bad type for loading", TypeNames(Entry->Type)); } return Reg; } -int AsStrLocalVar(int Register, int ID) { - printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type); +int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register) { + printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Entry->Name, Entry->Type); - switch(Symbols[ID].Type) { - case RET_CHAR: + int TypeSize = PrimitiveSize(Entry->Type); + switch(TypeSize) { + case 1: // movzbq zeroes, then moves a byte into the quad register - fprintf(OutputFile, "\tmovb\t%s, %d(\%%rbp)\n", ByteRegisters[Register], Symbols[ID].SinkOffset); + fprintf(OutputFile, "\tmovb\t%s, %d(\%%rbp)\n", ByteRegisters[Register], Entry->SinkOffset); break; - case RET_INT: - fprintf(OutputFile, "\tmovl\t%s, %d(\%%rbp)\n", DoubleRegisters[Register], Symbols[ID].SinkOffset); + case 4: + fprintf(OutputFile, "\tmovl\t%s, %d(\%%rbp)\n", DoubleRegisters[Register], Entry->SinkOffset); break; - case RET_LONG: - case PTR_CHAR: - case PTR_INT: - case PTR_LONG: - case PTR_VOID: - fprintf(OutputFile, "\tmovq\t%s, %d(%%rbp)\n", Registers[Register], Symbols[ID].SinkOffset); + case 8: + fprintf(OutputFile, "\tmovq\t%s, %d(%%rbp)\n", Registers[Register], Entry->SinkOffset); break; default: - DieMessage("Bad type for saving", TypeNames[Symbols[ID].Type]); + DieMessage("Bad type for saving", TypeNames(Entry->Type)); } return Register; } -int AsAddr(int ID) { +int AsAddr(struct SymbolTableEntry* Entry) { int Register = RetrieveRegister(); - printf("\tSaving pointer of %s into %s\n", Symbols[ID].Name, Registers[Register]); + printf("\tSaving pointer of %s into %s\n", Entry->Name, Registers[Register]); - fprintf(OutputFile, "\tleaq\t%s(%%rip), %s\n", Symbols[ID].Name, Registers[Register]); + fprintf(OutputFile, "\tleaq\t%s(%%rip), %s\n", Entry->Name, Registers[Register]); return Register; } int AsDeref(int Reg, int Type) { + int DestSize = PrimitiveSize(ValueAt(Type)); + printf("\tDereferencing %s\n", Registers[Reg]); - switch(Type) { - case PTR_CHAR: + switch(DestSize) { + case 1: fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], Registers[Reg]); break; - case PTR_INT: - case PTR_LONG: + case 2: + fprintf(OutputFile, "\tmovslq\t(%s), %s\n", Registers[Reg], Registers[Reg]); + case 4: + case 8: fprintf(OutputFile, "\tmovq\t(%s), %s\n", Registers[Reg], Registers[Reg]); break; default: @@ -719,22 +711,22 @@ int AsStrDeref(int Register1, int Register2, int Type) { return Register1; } -void AsGlobalSymbol(int ID) { +void AsGlobalSymbol(struct SymbolTableEntry* Entry) { int TypeSize; - TypeSize = PrimitiveSize(Symbols[ID].Type); + TypeSize = PrimitiveSize(Entry->Type); fprintf(OutputFile, "\t.data\n" "\t.globl\t%s\n", - Symbols[ID].Name); + Entry->Name); - fprintf(OutputFile, "%s:\n", Symbols[ID].Name); + fprintf(OutputFile, "%s:\n", Entry->Name); - for(int i = 0; i < Symbols[ID].Length; i++) { + for(int i = 0; i < Entry->Length; i++) { switch(TypeSize) { - case 1: fprintf(OutputFile, "\t.byte\t0\r\n", Symbols[ID].Name); break; - case 4: fprintf(OutputFile, "\t.long\t0\r\n", Symbols[ID].Name); break; - case 8: fprintf(OutputFile, "\t.quad\t0\r\n", Symbols[ID].Name); break; + case 1: fprintf(OutputFile, "\t.byte\t0\r\n", Entry->Name); break; + case 4: fprintf(OutputFile, "\t.long\t0\r\n", Entry->Name); break; + case 8: fprintf(OutputFile, "\t.quad\t0\r\n", Entry->Name); break; default: DieDecimal("Unknown type in AsNewSymbol", TypeSize); break; } } @@ -746,13 +738,13 @@ int AsCallWrapper(struct ASTNode* Node) { while(CompositeTree) { Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation); - AsCopyArgs(Register, CompositeTree->Value.Size); - if(Args == 0) Args = CompositeTree->Value.Size; + AsCopyArgs(Register, CompositeTree->Size); + if(Args == 0) Args = CompositeTree->Size; DeallocateAllRegisters(); CompositeTree = CompositeTree->Left; } - return AsCall(Node->Value.ID, Args); + return AsCall(Node->Symbol, Args); } void AsCopyArgs(int Register, int Position) { @@ -763,14 +755,14 @@ void AsCopyArgs(int Register, int Position) { } } -int AsCall(int FuncID, int Args) { +int AsCall(struct SymbolTableEntry* Entry, int Args) { int OutRegister = RetrieveRegister(); - printf("\t\tCalling function %s with %d parameters\n", Symbols[FuncID].Name, Args); + printf("\t\tCalling function %s with %d parameters\n", Entry->Name, Args); printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]); - fprintf(OutputFile, "\tcall\t%s\n", Symbols[FuncID].Name); + fprintf(OutputFile, "\tcall\t%s\n", Entry->Name); if(Args > 4) fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4)); @@ -779,11 +771,11 @@ int AsCall(int FuncID, int Args) { return OutRegister; } -int AsReturn(int Register, int FuncID) { +int AsReturn(struct SymbolTableEntry* Entry, int Register) { - printf("\t\tCreating return for function %s\n", Symbols[FuncID].Name); + printf("\t\tCreating return for function %s\n", Entry->Name); - switch(Symbols[FuncID].Type) { + switch(Entry->Type) { case RET_CHAR: fprintf(OutputFile, "\tmovzbl\t%s, %%eax\n", ByteRegisters[Register]); break; @@ -797,11 +789,11 @@ int AsReturn(int Register, int FuncID) { break; default: - DieMessage("Bad function type in generating return", TypeNames[Symbols[FuncID].Type]); + DieMessage("Bad function type in generating return", TypeNames(Entry->Type)); } - AsJmp(Symbols[FuncID].EndLabel); + AsJmp(Entry->EndLabel); } @@ -920,9 +912,10 @@ void AssemblerPreamble() { OutputFile); } -void AsFunctionPreamble(int FunctionID) { - char* Name = Symbols[FunctionID].Name; - int ParamOffset = 0, ParamReg = 9; +void AsFunctionPreamble(struct SymbolTableEntry* Entry) { + char* Name = Entry->Name; + struct SymbolTableEntry* Param, *Local; + int ParamOffset = 0, ParamReg = 9, ParamCount = 0; LocalVarOffset = 4; // Prepare parameters @@ -943,24 +936,19 @@ void AsFunctionPreamble(int FunctionID) { int LoopIndex; // If we have parameters, move them to the last 4 registers - for(LoopIndex = SYMBOLS - 1; LoopIndex > CurrentLocal; LoopIndex--) { - if(Symbols[LoopIndex].Storage != SC_PARAM) - break; - if(LoopIndex < SYMBOLS - 4) // We only have 4 argument registers - break; + for(Param = Entry->Start, ParamCount = 1; Param != NULL; Param = Param->NextSymbol, ParamCount++) { + if(ParamCount > 4) { // We only have 4 argument registers + Param->SinkOffset = ParamOffset; + ParamOffset += 8; + } - Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type); - AsStrLocalVar(ParamReg--, LoopIndex); + Entry->SinkOffset = AsCalcOffset(Param->Type); + AsStrLocalVar(Param, ParamReg--); } // If we have more parameters, move them to the stack - for(; LoopIndex > CurrentLocal; LoopIndex--) { - if(Symbols[LoopIndex].Storage == SC_PARAM) { - Symbols[LoopIndex].SinkOffset = ParamOffset + 16; - ParamOffset += 8; - } else { - Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type); - } + for(Local = Locals; Local != NULL; Local = Local->NextSymbol) { + Local->SinkOffset = AsCalcOffset(Local->Type); } // With all the parameters on the stack, we can allocate the shadow space @@ -970,8 +958,8 @@ void AsFunctionPreamble(int FunctionID) { } -void AsFunctionEpilogue(int FunctionID) { - AsLabel(Symbols[FunctionID].EndLabel); +void AsFunctionEpilogue(struct SymbolTableEntry* Entry) { + AsLabel(Entry->EndLabel); fprintf(OutputFile, "\tpopq\t%%rbp\n" diff --git a/src/Dump.c b/src/Dump.c index 4225af6..f80dfef 100644 --- a/src/Dump.c +++ b/src/Dump.c @@ -12,27 +12,27 @@ static int GenerateSrg() { return srgId++; } -void DumpTree(struct ASTNode* node, int level) { +void DumpTree(struct ASTNode* Node, int level) { int Lfalse, Lstart, Lend; // Handle weirdo loops and conditions first. - switch(node->Operation) { + switch(Node->Operation) { case OP_IF: Lfalse = GenerateSrg(); for(int i = 0; i < level; i++) fprintf(stdout, " "); fprintf(stdout, "IF"); - if(node->Right) { + if(Node->Right) { Lend = GenerateSrg(); fprintf(stdout, ", end label %d", Lend); } fprintf(stdout, "\n"); - DumpTree(node->Left, level + 2); - DumpTree(node->Middle, level + 2); + DumpTree(Node->Left, level + 2); + DumpTree(Node->Middle, level + 2); - if(node->Right) - DumpTree(node->Right, level + 2); + if(Node->Right) + DumpTree(Node->Right, level + 2); return; case OP_LOOP: @@ -41,28 +41,28 @@ void DumpTree(struct ASTNode* node, int level) { fprintf(stdout, " "); fprintf(stdout, "LOOP starts at %d\n", Lstart); Lend = GenerateSrg(); - DumpTree(node->Left, level + 2); - DumpTree(node->Right, level + 2); + DumpTree(Node->Left, level + 2); + DumpTree(Node->Right, level + 2); return; } // If current node is a compound, we treat it as if we didn't just enter a loop. - if(node->Operation == OP_COMP) + if(Node->Operation == OP_COMP) level = -2; - if(node->Left) - DumpTree(node->Left, level + 2); + if(Node->Left) + DumpTree(Node->Left, level + 2); - if(node->Right) - DumpTree(node->Right, level + 2); + if(Node->Right) + DumpTree(Node->Right, level + 2); // The meat of this operation! for(int i = 0; i < level; i++) fprintf(stdout, " "); - switch (node->Operation){ + switch (Node->Operation){ case OP_COMP: fprintf(stdout, "\n\n"); return; - case OP_FUNC: fprintf(stdout, "OP_FUNC %s\n", Symbols[node->Value.ID].Name); return; + case OP_FUNC: fprintf(stdout, "OP_FUNC %s\n", Node->Symbol->Name); return; case OP_ADD: fprintf(stdout, "OP_ADD\n"); return; case OP_SUBTRACT: fprintf(stdout, "OP_SUBTRACT\n"); return; case OP_MULTIPLY: fprintf(stdout, "OP_MULTIPLY\n"); return; @@ -73,22 +73,22 @@ void DumpTree(struct ASTNode* node, int level) { case OP_GREAT: fprintf(stdout, "OP_GREAT\n"); return; case OP_LESSE: fprintf(stdout, "OP_LESSE\n"); return; case OP_GREATE: fprintf(stdout, "OP_GREATE\n"); return; - case TERM_INTLITERAL: fprintf(stdout, "TERM_INTLITERAL %d\n", node->Value.IntValue); return; - case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", node->Value.IntValue); return; + case TERM_INTLITERAL: fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue); return; + case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue); return; case REF_IDENT: - if(node->RVal) - fprintf(stdout, "REF_IDENT rval %s\n", Symbols[node->Value.ID].Name); + if(Node->RVal) + fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name); else - fprintf(stdout, "REF_IDENT %s\n", Symbols[node->Value.ID].Name); + fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name); return; case OP_ASSIGN: fprintf(stdout, "OP_ASSIGN\n"); return; case OP_WIDEN: fprintf(stdout, "OP_WIDEN\n"); return; case OP_RET: fprintf(stdout, "OP_RET\n"); return; - case OP_CALL: fprintf(stdout, "OP_CALL %s\n", Symbols[node->Value.ID].Name); return; - case OP_ADDRESS: fprintf(stdout, "OP_ADDRESS %s\n", Symbols[node->Value.ID].Name); return; + case OP_CALL: fprintf(stdout, "OP_CALL %s\n", Node->Symbol->Name); return; + case OP_ADDRESS: fprintf(stdout, "OP_ADDRESS %s\n", Node->Symbol->Name); return; 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; + fprintf(stdout, "OP_DEREF %s\n", Node->RVal ? "rval" : ""); return; + case OP_SCALE: fprintf(stdout, "OP_SCALE %s\n", TypeNames(Node->Size)); return; case OP_BOOLOR: fprintf(stdout, "OP_BOOLOR\n"); return; case OP_BOOLAND: fprintf(stdout, "OP_BOOLAND\n"); return; @@ -111,7 +111,7 @@ void DumpTree(struct ASTNode* node, int level) { case OP_BOOLCONV: fprintf(stdout, "OP_BOOLCONV\n"); return; default: - DieDecimal("Unknown Dump Operator", node->Operation); + DieDecimal("Unknown Dump Operator", Node->Operation); } } \ No newline at end of file diff --git a/src/Main.c b/src/Main.c index 8aa2ad1..70d8dde 100644 --- a/src/Main.c +++ b/src/Main.c @@ -10,7 +10,7 @@ #include -int TypeSizes[9] = { 0, 1, 4, 8, 0, 8, 8, 8, 8}; // in BYTES +int TypeSizes[5] = { 0, 1, 4, 8, 0}; // in BYTES char* TokenNames[] = { "End of file", @@ -76,9 +76,6 @@ char* TokenNames[] = { "Return keyword" }; -char* TypeNames[9] = { "none", "char", "int", "long", "void", "charptr", "intptr", "longptr", "voidptr"}; - - int main(int argc, char* argv[]) { /* Line = 1; Overread = '\n'; diff --git a/src/Parser.c b/src/Parser.c index fbb8a2c..fecf4b0 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -52,33 +52,35 @@ struct ASTNode* ConstructASTNode(int Operation, int Type, struct ASTNode* Left, struct ASTNode* Middle, struct ASTNode* Right, + struct SymbolTableEntry* Symbol, int IntValue) { + struct ASTNode* Node; Node = (struct ASTNode*) malloc(sizeof(struct ASTNode)); - if(!Node) { - fprintf(stderr, "Unable to allocate node!"); - exit(1); - } + if(!Node) + Die("Unable to allocate node!"); + Node->Operation = Operation; Node->ExprType = Type; Node->Left = Left; Node->Middle = Middle; Node->Right = Right; - Node->Value.IntValue = IntValue; + Node->Symbol = Symbol; + Node->IntValue = IntValue; return Node; } -struct ASTNode* ConstructASTLeaf(int Operation, int Type, int IntValue) { - return ConstructASTNode(Operation, Type, NULL, NULL, NULL, IntValue); +struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue) { + return ConstructASTNode(Operation, Type, NULL, NULL, NULL, Symbol, IntValue); } -struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, int IntValue) { - return ConstructASTNode(Operation, Type, Left, NULL, NULL, IntValue); +struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue) { + return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue); } @@ -116,15 +118,15 @@ struct ASTNode* ParsePrimary(void) { case LI_INT: if((CurrentToken.value >= 0) && (CurrentToken.value < 256)) - Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, CurrentToken.value); + Node = ConstructASTLeaf(TERM_INTLITERAL, RET_CHAR, NULL, CurrentToken.value); else - Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, CurrentToken.value); + Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value); break; case LI_STR: ID = AsNewString(CurrentIdentifier); - Node = ConstructASTLeaf(TERM_STRLITERAL, PTR_CHAR, ID); + Node = ConstructASTLeaf(TERM_STRLITERAL, PointerTo(RET_CHAR), NULL, ID); break; case TY_IDENTIFIER: @@ -196,8 +198,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) { //printf("\tAssigning variable: %s value %d\n", Symbols[FindSymbol(CurrentIdentifier)].Name, RightNode->Value.IntValue); // LeftNode holds the target, the target variable in this case - printf("\t\tAssigning variable: %s\n", Symbols[LeftNode->Value.ID].Name); - printf("\t\tAfter parsing, the identifier name is %s, id %d in the symbol table.\n", Symbols[LeftNode->Value.ID].Name, LeftNode->Value.ID); + printf("\t\tAssigning variable: %s\n", LeftNode->Symbol->Name); LeftTemp = LeftNode; LeftNode = RightNode; @@ -253,7 +254,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) { if(RightTemp != NULL) RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0); - LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, 0); + LeftNode = ConstructASTNode(ParseTokenToOperation(NodeType), LeftNode->ExprType, LeftNode, NULL, RightNode, NULL, 0); NodeType = CurrentToken.type; if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) { LeftNode->RVal = 1; @@ -367,17 +368,17 @@ int ParseAST(struct ASTNode* Node) { struct ASTNode* CallFunction() { struct ASTNode* Tree; - int FuncID; + struct SymbolTableEntry* Function; //TODO: Test structural type! - if((FuncID = FindSymbol(CurrentIdentifier)) == -1 && (Symbols[FuncID].Structure == ST_FUNC)) + if((Function = FindSymbol(CurrentIdentifier)) == NULL || (Function->Structure != ST_FUNC)) DieMessage("Undeclared function", CurrentIdentifier); VerifyToken(LI_LPARE, "("); Tree = GetExpressionList(); - Tree = ConstructASTBranch(OP_CALL, Symbols[FuncID].Type, Tree, FuncID); + Tree = ConstructASTBranch(OP_CALL, Function->Type, Tree, Function, 0); VerifyToken(LI_RPARE, ")"); @@ -392,7 +393,7 @@ struct ASTNode* GetExpressionList() { Child = ParsePrecedenceASTNode(0); Count++; - Tree = ConstructASTNode(OP_COMP, PTR_VOID, Tree, NULL, Child, Count); + Tree = ConstructASTNode(OP_COMP, PointerTo(RET_VOID), Tree, NULL, Child, NULL, Count); switch(CurrentToken.type) { case LI_COM: @@ -475,7 +476,7 @@ struct ASTNode* ParseCompound() { if(Left == NULL) Left = Tree; else - Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, 0); + Left = ConstructASTNode(OP_COMP, RET_NONE, Left, NULL, Tree, NULL, 0); } if(CurrentToken.type == LI_RBRAC) { @@ -507,7 +508,7 @@ void ParseGlobals() { printf("\tParsing function"); Tree = ParseFunction(Type); if(Tree) { - printf("\nBeginning assembler creation of new function %s\n", Symbols[Tree->Value.ID].Name); + printf("\nBeginning assembler creation of new function %s\n", Tree->Symbol->Name); AssembleTree(Tree, -1, 0); FreeLocals(); } else { diff --git a/src/Pointers.c b/src/Pointers.c index f7a2666..002d8cb 100644 --- a/src/Pointers.c +++ b/src/Pointers.c @@ -8,45 +8,39 @@ #include int PointerTo(int Type) { - //Type = Type + 1; - printf("\t\tPointerising a %s\n", TypeNames[Type]); - // As it stands, the conversion between - // RET and PTR is +4. - // TODO: if we add types, increase this number - // TODO: Make this a proper translation table - // TODO: More checks! This can go wrong easily! - if(Type >= RET_CHAR && Type <= RET_VOID) { - return Type + (PTR_CHAR - RET_CHAR); - } else { - DieDecimal("Unable to create a pointer to the desired type", Type); - } - - return -1; + if((Type & 0xf) == 0xf) + DieDecimal("Unrecognized type in pointerisation", Type); + printf("\t\tPointerising a %s\n", TypeNames(Type)); + return (Type + 1); } int ValueAt(int Type) { - - printf("\t\tDereferencing a %s\n", TypeNames[Type]); + printf("\t\tDereferencing a %s\n", TypeNames(Type)); //TODO: this is still bullshittery! - if(Type >= PTR_CHAR && Type <= PTR_VOID) { - printf("\t\t\tDereference of %s is %s.\r\n", TypeNames[Type], TypeNames[Type - 4]); - return Type - 4; - } else { - DieDecimal("Unable to dereference type", Type); - } - return -1; + if((Type & 0xf) == 0x0) + DieDecimal("Unrecognized type in defererencing", Type); + return (Type - 1); } int ParseOptionalPointer() { int Type; - // TODO: THIS IS WRONG AND SHOULD NOT EXIST - - if(CurrentToken.type >= TY_CHAR && CurrentToken.type <= TY_VOID) { - Type = CurrentToken.type - (TY_CHAR - RET_CHAR); - printf("\t\tConverting a %s token to a %s type.\n", TokenNames[CurrentToken.type], TypeNames[Type]); - } else { - DieDecimal("Illegal type for pointerisation", CurrentToken.type); + + switch(CurrentToken.type) { + case TY_VOID: + Type = RET_VOID; + break; + case TY_CHAR: + Type = RET_CHAR; + break; + case TY_INT: + Type = RET_INT; + break; + case TY_LONG: + Type = RET_LONG; + break; + default: + DieDecimal("Illegal type for pointerisation", CurrentToken.type); } // Recursively scan more *s // This makes things like: @@ -66,13 +60,13 @@ int ParseOptionalPointer() { struct ASTNode* AccessArray() { struct ASTNode* LeftNode, *RightNode; - int ID; + struct SymbolTableEntry* Entry; printf("\tAccessing array %s as requested\r\n", CurrentIdentifier); - if ((ID = FindSymbol(CurrentIdentifier)) == -1 || Symbols[ID].Structure != ST_ARR) + if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR) DieMessage("Accessing undeclared array", CurrentIdentifier); - LeftNode = ConstructASTLeaf(OP_ADDRESS, Symbols[ID].Type, ID); + LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0); //printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]); Tokenise(&CurrentToken); //printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]); @@ -84,12 +78,12 @@ struct ASTNode* AccessArray() { if(!TypeIsInt(RightNode->ExprType)) Die("Array index is not integer"); - printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", TypeNames[RightNode->ExprType], TypeNames[LeftNode->ExprType]); + printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType), TypeNames(LeftNode->ExprType)); RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD); - LeftNode = ConstructASTNode(OP_ADD, Symbols[ID].Type, LeftNode, NULL, RightNode, 0); + LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0); printf("\tAccessArray: Preparing LeftNode for dereference.\r\n"); - LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, 0); + LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, NULL, 0); printf("\tArray Access constructed\r\n"); return LeftNode; } \ No newline at end of file diff --git a/src/Statements.c b/src/Statements.c index 0019d50..1aa4b89 100644 --- a/src/Statements.c +++ b/src/Statements.c @@ -8,21 +8,21 @@ #include #include -static int ReadParameters(int FuncID) { - int TokenType, ParamCount = 0, ProtoParamCount, ParamIndex; - ParamIndex = FuncID + 1; - if(ParamIndex) // If FuncID > -1 (If the function exists) - ProtoParamCount = Symbols[FuncID].Length; // Set the prototype length +static int ReadParameters(struct SymbolTableEntry* FunctionSymbol) { + int TokenType, ParamCount = 0; + struct SymbolTableEntry* PrototypePointer = NULL; + if(FunctionSymbol != NULL) + PrototypePointer = FunctionSymbol->Start; while(CurrentToken.type != LI_RPARE) { TokenType = ParseOptionalPointer(); VerifyToken(TY_IDENTIFIER, "identifier"); - if(ParamIndex) { - if(TokenType != Symbols[FuncID].Type) + if(PrototypePointer != NULL) { + if(TokenType != PrototypePointer->Type) DieDecimal("Function paramater of invalid type at index", ParamCount + 1); - ParamIndex++; + PrototypePointer=PrototypePointer->NextSymbol; } else { BeginVariableDeclaration(TokenType, SC_PARAM); } @@ -39,8 +39,8 @@ static int ReadParameters(int FuncID) { } } - if((FuncID != -1) && (ParamCount != ProtoParamCount)) - DieMessage("Invalid number of parameters in prototyped function", Symbols[FuncID].Name); + if((FunctionSymbol != NULL) && (ParamCount != FunctionSymbol->Length)) + DieMessage("Invalid number of parameters in prototyped function", FunctionSymbol->Name); return ParamCount; } @@ -49,77 +49,86 @@ static int ReadParameters(int FuncID) { * Handles the declaration of a type of a variable. * int newVar; * - * It verifies that we have the `int` keyword followed by a + * It verifies that we have a type keyword followed by a * unique, non-keyword identifier. * - * It then stores this variable into the symbol table. - * - * //TODO: Assemble this into the symbol table. - * //TODO: int i = 5; + * It then stores this variable into the symbol table, + * and returns the new item. * */ -void BeginVariableDeclaration(int Type, int Scope) { - int ID; - printf("type: %s\n", TypeNames[Type]); +struct SymbolTableEntry* BeginVariableDeclaration(int Type, int Scope) { + struct SymbolTableEntry* Symbol = NULL; + + switch(Scope) { + case SC_GLOBAL: + if(FindGlobal(CurrentIdentifier) != NULL) + DieMessage("Invalid redeclaration of global variable", CurrentIdentifier); + case SC_LOCAL: + case SC_PARAM: + if(FindLocal(CurrentIdentifier) != NULL) + DieMessage("Invalid redelcaration of local variable", CurrentIdentifier); + } if(CurrentToken.type == LI_LBRAS) { Tokenise(&CurrentToken); - //Type = Type - 2; + if(CurrentToken.type == LI_INT) { - printf("Adding array %s that is %d x %s.\r\n", CurrentIdentifier, CurrentToken.value, TypeNames[Type]); - if(Scope == SC_LOCAL) - Die("Local arrays are not supported"); - else - AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 0, CurrentToken.value); + switch(Scope) { + case SC_GLOBAL: + Symbol = AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 1, 0); + break; + case SC_LOCAL: + case SC_PARAM: + Die("Local arrays are unimplemented"); + } } Tokenise(&CurrentToken); VerifyToken(LI_RBRAS, "]"); } else { - printf("Adding var %s that is a %s\r\n", CurrentIdentifier, TypeNames[Type]); - if(Scope == SC_LOCAL) { - if(AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 0, 1) == -1) - Die("Illegal state: Identical locals in current function"); - } else { - AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 0, 1); - } + Symbol = AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 1, 0); } - //VerifyToken(LI_SEMIC, ";"); + return Symbol; + } struct ASTNode* ParseFunction(int Type) { struct ASTNode* Tree; struct ASTNode* FinalStatement; + struct SymbolTableEntry* OldFunction, *NewFunction = NULL; int SymbolSlot, BreakLabel, ParamCount, ID; - if((ID = FindSymbol(CurrentIdentifier)) != -1) - if(Symbols[ID].Structure != ST_FUNC) - ID = -1; - - printf("\nIdentified%sfunction %s of return type %s, end label %d\n", (ID == -1) ? " new " : " overloaded ", CurrentIdentifier, TypeNames[Type], BreakLabel); - - if(ID == -1) { - SymbolSlot = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 1); - CurrentFunction = SymbolSlot; + if((OldFunction = FindSymbol(CurrentIdentifier)) != NULL) + if(OldFunction->Storage != ST_FUNC) + OldFunction = NULL; + if(OldFunction == NULL) { BreakLabel = NewLabel(); + NewFunction = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 0); } VerifyToken(LI_LPARE, "("); - ParamCount = ReadParameters(ID); + ParamCount = ReadParameters(OldFunction); VerifyToken(LI_RPARE, ")"); - if(ID == -1) { - Symbols[SymbolSlot].Length = ParamCount; - ID = SymbolSlot; + if(NewFunction) { + NewFunction->Elements = ParamCount; + NewFunction->Start = Params; + OldFunction = NewFunction; } + Params = ParamsEnd = NULL; + if(CurrentToken.type == LI_SEMIC) { Tokenise(&CurrentToken); return NULL; } + + printf("\nIdentified%sfunction %s of return type %s, end label %d\n", (OldFunction == NULL) ? " new " : " overloaded ", OldFunction->Name, TypeNames(Type), BreakLabel); + FunctionEntry = OldFunction; + Tree = ParseCompound(); if(Type != RET_VOID) { @@ -132,7 +141,7 @@ struct ASTNode* ParseFunction(int Type) { } - return ConstructASTBranch(OP_FUNC, Tree->ExprType, Tree, SymbolSlot); + return ConstructASTBranch(OP_FUNC, Tree->ExprType, Tree, OldFunction, BreakLabel); } /* @@ -145,10 +154,10 @@ struct ASTNode* ParseFunction(int Type) { struct ASTNode* ReturnStatement() { struct ASTNode* Tree; - int ReturnType, FunctionType; + int ReturnType; - if(Symbols[CurrentFunction].Type == RET_VOID) + if(FunctionEntry->Type == RET_VOID) Die("Attempt to return from void function"); VerifyToken(KW_RETURN, "return"); @@ -162,7 +171,7 @@ struct ASTNode* ReturnStatement() { FunctionType = Symbols[CurrentFunction].Type; */ - Tree = MutateType(Tree, Symbols[CurrentFunction].Type, 0); + Tree = MutateType(Tree, FunctionEntry->Type, 0); if(Tree == NULL) Die("Returning a value of incorrect type for function"); @@ -171,9 +180,9 @@ struct ASTNode* ReturnStatement() { Tree = ConstructASTBranch(ReturnType, FunctionType, Tree, 0); */ - Tree = ConstructASTBranch(OP_RET, RET_NONE, Tree, 0); + Tree = ConstructASTBranch(OP_RET, RET_NONE, Tree, FunctionEntry, 0); - printf("\t\tReturning from function %s\n", Symbols[CurrentFunction].Name); + printf("\t\tReturning from function %s\n", FunctionEntry->Name); VerifyToken(LI_RPARE, ")"); // TODO: OPTIONALISE! @@ -245,7 +254,7 @@ struct ASTNode* IfStatement() { // No null checking, no arithmetic, no functions. // TODO: this if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) - Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0); + Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0); VerifyToken(LI_RPARE, ")"); @@ -256,7 +265,7 @@ struct ASTNode* IfStatement() { False = ParseCompound(); } - return ConstructASTNode(OP_IF, RET_NONE, Condition, True, False, 0); + return ConstructASTNode(OP_IF, RET_NONE, Condition, True, False, NULL, 0); } struct ASTNode* WhileStatement() { @@ -269,13 +278,13 @@ struct ASTNode* WhileStatement() { if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) - Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0); + Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0); VerifyToken(LI_RPARE, ")"); Body = ParseCompound(); - return ConstructASTNode(OP_LOOP, RET_NONE, Condition, NULL, Body, 0); + return ConstructASTNode(OP_LOOP, RET_NONE, Condition, NULL, Body, NULL, 0); } struct ASTNode* ForStatement() { @@ -298,7 +307,7 @@ struct ASTNode* ForStatement() { Condition = ParsePrecedenceASTNode(0); if(Condition->Operation < OP_EQUAL || Condition->Operation > OP_GREATE) - Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0); + Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0); VerifyToken(LI_SEMIC, ";"); @@ -308,13 +317,13 @@ struct ASTNode* ForStatement() { Body = ParseCompound(); // We need to be able to skip over the body and the postop, so we group them together. - Tree = ConstructASTNode(OP_COMP, RET_NONE, Body, NULL, Postop, 0); + Tree = ConstructASTNode(OP_COMP, RET_NONE, Body, NULL, Postop, NULL, 0); // We need to be able to jump to the top of the condition and fall through to the body, // so we group it with the last block - Tree = ConstructASTNode(OP_LOOP, RET_NONE, Condition, NULL, Tree, 0); + Tree = ConstructASTNode(OP_LOOP, RET_NONE, Condition, NULL, Tree, NULL, 0); // We need to append the postop to the loop, to form the final for loop - return ConstructASTNode(OP_COMP, RET_NONE, Preop, NULL, Tree, 0); + return ConstructASTNode(OP_COMP, RET_NONE, Preop, NULL, Tree, NULL, 0); } struct ASTNode* PrintStatement(void) { @@ -333,9 +342,9 @@ struct ASTNode* PrintStatement(void) { DieDecimal("Attempting to print an invalid type:", RightType); if(RightType) - Tree = ConstructASTBranch(RightType, RET_INT, Tree, 0); + Tree = ConstructASTBranch(RightType, RET_INT, Tree, NULL, 0); - Tree = ConstructASTBranch(OP_PRINT, RET_NONE, Tree, 0); + Tree = ConstructASTBranch(OP_PRINT, RET_NONE, Tree, NULL, 0); //ParseAST(Tree); @@ -345,7 +354,7 @@ struct ASTNode* PrintStatement(void) { struct ASTNode* PostfixStatement() { struct ASTNode* Tree; - int ID; + struct SymbolTableEntry* Entry; Tokenise(&CurrentToken); @@ -364,8 +373,7 @@ struct ASTNode* PostfixStatement() { // There's no guarantees that the variable is in // the symbol table, though. - ID = FindSymbol(CurrentIdentifier); - if(ID == -1 || Symbols[ID].Structure != ST_VAR) + if((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_VAR) DieMessage("Unknown Variable", CurrentIdentifier); // Here we check for postincrement and postdecrement. @@ -373,14 +381,14 @@ struct ASTNode* PostfixStatement() { switch(CurrentToken.type) { case PPMM_PLUS: Tokenise(&CurrentToken); - Tree = ConstructASTLeaf(OP_POSTINC, Symbols[ID].Type, ID); + Tree = ConstructASTLeaf(OP_POSTINC, Entry->Type, Entry, 0); break; case PPMM_MINUS: Tokenise(&CurrentToken); - Tree = ConstructASTLeaf(OP_POSTDEC, Symbols[ID].Type, ID); + Tree = ConstructASTLeaf(OP_POSTDEC, Entry->Type, Entry, 0); break; default: - Tree = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID); + Tree = ConstructASTLeaf(REF_IDENT, Entry->Type, Entry, 0); } return Tree; @@ -395,21 +403,21 @@ struct ASTNode* PrefixStatement() { Tokenise(&CurrentToken); Tree = PrefixStatement(); Tree->RVal = 1; - Tree = ConstructASTBranch(OP_BOOLNOT, Tree->ExprType, Tree, 0); + Tree = ConstructASTBranch(OP_BOOLNOT, Tree->ExprType, Tree, NULL, 0); break; case BIT_NOT: Tokenise(&CurrentToken); Tree = PrefixStatement(); Tree->RVal = 1; - Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, 0); + Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, NULL, 0); break; case AR_MINUS: Tokenise(&CurrentToken); Tree = PrefixStatement(); - Tree = ConstructASTBranch(OP_NEGATE, Tree->ExprType, Tree, 0); + Tree = ConstructASTBranch(OP_NEGATE, Tree->ExprType, Tree, NULL, 0); break; case PPMM_PLUS: @@ -418,7 +426,7 @@ struct ASTNode* PrefixStatement() { if(Tree->Operation != REF_IDENT) Die("++ not followed by identifier"); - Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, 0); + Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, NULL, 0); break; case PPMM_MINUS: @@ -428,7 +436,7 @@ struct ASTNode* PrefixStatement() { if(Tree->Operation != REF_IDENT) Die("-- not followed by identifier"); - Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, 0); + Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, NULL, 0); break; case BIT_AND: @@ -453,7 +461,7 @@ struct ASTNode* PrefixStatement() { if(Tree->Operation != REF_IDENT && Tree->Operation != OP_DEREF) Die("* must be followed by another * or an identifier."); - Tree = ConstructASTBranch(OP_DEREF, ValueAt(Tree->ExprType), Tree, 0); + Tree = ConstructASTBranch(OP_DEREF, ValueAt(Tree->ExprType), Tree, NULL, 0); break; default: diff --git a/src/Symbols.c b/src/Symbols.c index b83600a..780ae4b 100644 --- a/src/Symbols.c +++ b/src/Symbols.c @@ -7,105 +7,138 @@ #include #include -static int GlobalSymbols = 0; - - -int FindSymbolImpl(char* Symbol, int Storage) { - int Ind; - - for(Ind = (Storage == SC_GLOBAL /* Are we global scope? */ - ? 0 /* If so, start from the beginning */ - : CurrentLocal + 1 /* Else, go from the start of the local block */ - ); - Ind < (Storage == SC_GLOBAL /* Are we global scope? */ - ? CurrentGlobal /* If so, start searching at the start */ - : SYMBOLS /* Otherwise, start at the end and work backward */ - ); - Ind++) { - if(Storage == SC_GLOBAL && Symbols[Ind].Storage == SC_PARAM) continue; // Skip searching globals for parameters. - if(*Symbol == *Symbols[Ind].Name && !strcmp(Symbol, Symbols[Ind].Name)) { - printf("\t\tFound %s at %d\r\n", Symbol, Ind); - return Ind; - } - } - - return -1; -} - /* - * Find the position of a symbol in the symbol table. - * @Return the index into the symbol table if found, - * -1 if not found. - * Does not care about differentiating local or global. - * It will only be consistent. + * Find the position of a symbol in a given symbol table. + * @param Name: The string name of the symbol + * @param List: The linked list to search in. + * @return the list if found, + * NULL if no found. */ -int FindSymbol(char* Symbol) { - int Res; - // Prioritise local vars - if((Res = FindSymbolImpl(Symbol, SC_LOCAL)) == -1) - // Fallback to global vars. - return FindSymbolImpl(Symbol, SC_GLOBAL); - return Res; + +static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry* List) { + for(; List != NULL; List = List->NextSymbol) + if((List->Name != NULL) && !strcmp(Name, List->Name)) + return (List); + return NULL; } /* - * Append a new entry to the table of global symbols. - * @Return the index to the new entry + * Search all the tables for a symbol. + * Use the overrides for polluted types + * eg. if you need a global from a local scope + * + * @param Symbol: The string name of the symbol to search for + * @return the Node corresponding to the most likely + * symbol required. + * * - * Will kill the program if we run out. - * The death condition here is running into the local symbol table. - * //TODO: Dump symbols on death? */ -static int NewGlobalSymbol() { - int Pos; +struct SymbolTableEntry* FindSymbol(char* Symbol) { + struct SymbolTableEntry* Node; - if((Pos = (CurrentGlobal++)) >= CurrentLocal) { - printf("%d:%d\r\n", CurrentGlobal, CurrentLocal); - Die("Too many Global symbols"); + if(CurrentFunction) { + Node = SearchList(Symbol, FunctionEntry->Start); + if(Node) + return Node; } + + Node = SearchList(Symbol, Locals); + if(Node) + return Node; - return Pos; + return SearchList(Symbol, Globals); } /* - * Append a new entry to the table of local (function-local) symbols. - * @Return the index to the new entry - * - * Will kill the program if we run out. - * The death condition here is running into the global symbol table. - * //TODO: Dump symbols on death? + * An override for FindSymbol. + * Searches only the parameters and local variables. + * @param Symbol: The string name of the symbol to search for. + * @return a pointer to the node if found, else NULL */ -static int NewLocalSymbol() { - int Pos; - if((Pos = (CurrentLocal--)) <= CurrentGlobal) - Die("Too many Local symbols"); +struct SymbolTableEntry* FindLocal(char* Symbol) { + struct SymbolTableEntry* Node; - return Pos; + if(FunctionEntry) { + Node = SearchList(Symbol, FunctionEntry->Start); + if(Node) + return Node; + } + + return SearchList(Symbol, Locals); } /* - * Reset the local counter on functions. + * An override for FindSymbol. + * Searches only the global variables. + * @param Symbol: The string name of the symbol to search for. + * @return a pointer to the node if found, else NULL + * + */ +struct SymbolTableEntry* FindGlobal(char* Symbol) { + return SearchList(Symbol, Globals); +} + +/* + * Given a particular linked list, + * Take Node and append it to the Tail. + * + * If there is no tail, set it to the Head. + * This prevents orphaned lists. + * + * @param Head: The start of the desired linked list + * @param Tail: The end of the desired linked list + * @param Node: The new item to append + * + */ +void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node) { + if(Head == NULL || Tail == NULL || Node == NULL) + Die("Not enough data to append a symbol to the tables"); + + if(*Tail) { + (*Tail)->NextSymbol = Node; + *Tail = Node; + } else { + *Head = *Tail = Node; + } + + Node->NextSymbol = NULL; +} + + +/* + * Reset the local variables of functions. */ void FreeLocals() { - CurrentLocal = SYMBOLS - 1; + Locals = LocalsEnd = NULL; + Params = ParamsEnd = NULL; + +} + +/* + * Reset all tables. + */ +void ClearTables() { + Globals = GlobalsEnd = NULL; + Locals = LocalsEnd = NULL; + Params = ParamsEnd = NULL; } /* - * Add a symbol to the tables, and set all the metadata. + * Create a symbol item, and set all the metadata. * @param Name: The string representing the name of the symbol. * @param Type: The return type in terms of DataTypes enum values. * @param Structure: The type of symbol this is, in terms of StructureType enum. * @param Storage: The storage scope of this symbol. For functions this is always SC_GLOBAL (for now). Vars and Arrays can be GLOBAL or SC_LOCAL. - * @param EndLabel: The label # to jump to to exit the function or array, where appropriate. - * @param Length: The size of the struct/array in units of 1xbase + * @param Length: The label # to jump to to exit the function or array, where appropriate. + * The size of the struct/array in units of 1xbase * - * @return The ID in the symbol table that now represents this symbol. + * @return The SymbolTableEntry* pointer that corresponds to this newly constructed node. */ -int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length) { +struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset) { - int TableSlot; + /* int TableSlot; int SinkOffset = 0; if((TableSlot = FindSymbolImpl(Name, Storage)) != -1) @@ -130,17 +163,32 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in TableSlot = NewLocalSymbol(); SinkOffset = AsCalcOffset(Type); break; + } */ + + struct SymbolTableEntry* Node = + (struct SymbolTableEntry*) malloc(sizeof(struct SymbolTableEntry)); + + Node->Name = strdup(Name); + Node->Type = Type; + Node->Structure = Structure; + Node->Storage = Storage; + Node->Length = Length; + Node->SinkOffset = SinkOffset; + + switch(Storage) { + case SC_GLOBAL: + AppendSymbol(&Globals, &GlobalsEnd, Node); + if(Structure != ST_FUNC) AsGlobalSymbol(Node); + break; + case SC_LOCAL: + AppendSymbol(&Locals, &LocalsEnd, Node); + break; + case SC_PARAM: + AppendSymbol(&Params, &ParamsEnd, Node); + break; } - Symbols[TableSlot].Name = strdup(Name); - Symbols[TableSlot].Type = Type; - Symbols[TableSlot].Structure = Structure; - Symbols[TableSlot].Storage = Storage; - Symbols[TableSlot].Length = Length; - Symbols[TableSlot].SinkOffset = SinkOffset; - Symbols[TableSlot].EndLabel = EndLabel; - - // NOTE: Generating global symbol names must happen AFTER the name and type are declared. + /* // NOTE: Generating global symbol names must happen AFTER the name and type are declared. switch(Storage) { case SC_GLOBAL: printf("\tCreating new global symbol %s into slot %d\r\n", Name, TableSlot); @@ -151,8 +199,8 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in break; case SC_LOCAL: break; - } + } */ //printf("Adding new variable %s of type %s to the table at %d\n", CurrentIdentifier, Types[Type], TableSlot); - return TableSlot; + return Node; } \ No newline at end of file diff --git a/src/Types.c b/src/Types.c index 0a0e300..e165ac5 100644 --- a/src/Types.c +++ b/src/Types.c @@ -9,15 +9,11 @@ int TypeIsInt(int Type) { - if(Type == RET_CHAR || Type == RET_INT || Type == RET_LONG) - return 1; - return 0; + return ((Type & 0xf) == 0); } int TypeIsPtr(int Type) { - if(Type == PTR_VOID || Type == PTR_CHAR || Type == PTR_INT || Type == PTR_LONG) - return 1; - return 0; + return ((Type & 0xf) != 0); } /* @@ -33,10 +29,32 @@ int TypeIsPtr(int Type) { */ int PrimitiveSize(int Type) { - if(Type < RET_NONE || Type > PTR_VOID) - DieDecimal("Checking size of bad data type", Type); - return TypeSizes[Type]; + if(TypeIsPtr(Type)) return 8; + switch(Type) { + case RET_CHAR: return 1; + case RET_INT: return 4; + case RET_LONG: return 8; + default: + DieDecimal("Bad type in PrimitiveSize", Type); + } + return 0; +} + +static char TypeBuffer[7]; + +char* TypeNames(int Type) { + switch(Type) { + case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break; + case RET_INT: memcpy(TypeBuffer, "Int ", 4); break; + case RET_LONG: memcpy(TypeBuffer, "Long", 4); break; + case RET_VOID: memcpy(TypeBuffer, "Void", 4); break; + default: DieDecimal("Bad size for printing", Type); + }; + if(TypeIsPtr(Type)) memcpy((void*)((size_t) TypeBuffer + 4), "Ptr", 3); + else memcpy((void*)((size_t) TypeBuffer + 4), " ", 3); + return TypeBuffer; + } /* @@ -180,7 +198,7 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) { */ if(RightSize > LeftSize) - return ConstructASTBranch(OP_WIDEN, RightType, Tree, 0); + return ConstructASTBranch(OP_WIDEN, RightType, Tree, NULL, 0); } // Left branch pointers are compatible if we're not doing operations @@ -206,7 +224,7 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) { RightSize = PrimitiveSize(ValueAt(RightType)); if(RightSize > 1) - return ConstructASTBranch(OP_SCALE, RightType, Tree, RightSize); + return ConstructASTBranch(OP_SCALE, RightType, Tree, NULL, RightSize); } }