Major rewrite of the symbol parsing

Moved from a static double-ended list to individual singly-linked lists for easier and faster parsing
This commit is contained in:
Curle 2021-01-20 01:05:41 +00:00
parent a52779e379
commit eb118db872
No known key found for this signature in database
GPG Key ID: 58A5C4688ECE6E7C
10 changed files with 510 additions and 432 deletions

View File

@ -15,7 +15,9 @@
#define TEXTLEN 512 #define TEXTLEN 512
#define SYMBOLS 1024 #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 OptDumpTree;
extern_ bool OptKeepAssembly; extern_ bool OptKeepAssembly;
@ -26,12 +28,12 @@ extern_ bool OptVerboseOutput;
extern_ char* OutputFileName; extern_ char* OutputFileName;
extern_ char* CurrentASMFile, *CurrentObjectFile; extern_ char* CurrentASMFile, *CurrentObjectFile;
extern_ int TypeSizes[9]; extern_ int TypeSizes[5];
extern_ char* TypeNames[9];
extern_ char* TokenNames[]; extern_ char* TokenNames[];
extern_ int CurrentFunction; extern_ int CurrentFunction;
extern_ struct SymbolTableEntry* FunctionEntry;
extern_ int Line; extern_ int Line;
extern_ int Overread; extern_ int Overread;

View File

@ -174,11 +174,12 @@ struct ASTNode {
struct ASTNode* Left; struct ASTNode* Left;
struct ASTNode* Middle; struct ASTNode* Middle;
struct ASTNode* Right; struct ASTNode* Right;
struct SymbolTableEntry* Symbol;
union { union {
int Size; // OP_SCALE's linear representation int Size; // OP_SCALE's linear representation
int IntValue; // TERM_INTLIT's Value int IntValue; // TERM_INTLIT's Value
int ID; // LV_IDENT's Symbols[] index. int ID; // LV_IDENT's Symbols[] index.
} Value; };
}; };
struct Token { struct Token {
@ -191,14 +192,25 @@ struct Token {
* assorted goodies. * assorted goodies.
*/ */
struct SymbolTable { struct SymbolTableEntry {
char* Name; char* Name;
int Type; // An entry in DataTypes, referring to the type of this data 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 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 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 { enum StorageScope {
@ -212,22 +224,23 @@ enum StorageScope {
/* /*
* The primitive data types for the language * The types of data being held in memory.
* //TODO: Move back into TokenTypes * 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 { enum DataTypes {
RET_NONE, // No return type. Literal void. RET_NONE, // No return type. Literal void.
RET_CHAR, // "char" type keyword RET_CHAR = 16, // "char" type keyword
RET_INT, // "int" type keyword RET_INT = 32, // "int" type keyword
RET_LONG, // "long" type keyword RET_LONG = 48, // "long" type keyword
RET_VOID, // "void" type keyword RET_VOID = 64, // "void" type keyword
// Pointer types
PTR_CHAR,
PTR_INT,
PTR_LONG,
PTR_VOID,
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 TypeIsInt(int Type);
int TypeIsPtr(int Type); int TypeIsPtr(int Type);
char* TypeNames(int Type);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * S Y N T A X T R E E * * * * * * * * * * * * 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* Left,
struct ASTNode* Middle, struct ASTNode* Middle,
struct ASTNode* Right, struct ASTNode* Right,
struct SymbolTableEntry* Symbol,
int IntValue); 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 * * * * * * * * * * * * 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 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 * * * * * * * * 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 AsSub(int Left, int Right);
int AsDiv(int Left, int Right); int AsDiv(int Left, int Right);
int AsLdGlobalVar(int ID, int Operation); int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation);
int AsLdLocalVar(int ID, int Operation); int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation);
int AsStrGlobalVar(int Register, int ID); int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register);
int AsStrLocalVar(int Register, int ID); int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register);
int AsCalcOffset(int Type); int AsCalcOffset(int Type);
void AsNewStackFrame(); void AsNewStackFrame();
int AsDeref(int Reg, int Type); int AsDeref(int Reg, int Type);
int AsStrDeref(int Register1, int Register2, 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); int AsNewString(char* Value);
@ -420,25 +442,25 @@ void AsLabel(int Label);
int AsShl(int Register, int Val); int AsShl(int Register, int Val);
int AsReturn(int Register, int FuncID); int AsReturn(struct SymbolTableEntry* Entry, int Register);
int AsCallWrapper(struct ASTNode* Node); int AsCallWrapper(struct ASTNode* Node);
void AsCopyArgs(int Register, int Position); void AsCopyArgs(int Register, int Position);
int AsCall(int Register, int FuncID); int AsCall(struct SymbolTableEntry* Entry, int Args);
int AsWhile(struct ASTNode* Node); int AsWhile(struct ASTNode* Node);
void AssemblerPrint(int Register); void AssemblerPrint(int Register);
void AssemblerPreamble(); void AssemblerPreamble();
void AsFunctionPreamble(int ID); void AsFunctionPreamble(struct SymbolTableEntry* Entry);
void AsFunctionEpilogue(int ID); void AsFunctionEpilogue(struct SymbolTableEntry* Entry);
/* * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * *
* * * * D E C L A R A T I O N * * * * * * * * 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* ParseIdentifier(void);
struct ASTNode* IfStatement(); struct ASTNode* IfStatement();

View File

@ -70,9 +70,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
return (AsCallWrapper(Node)); return (AsCallWrapper(Node));
case OP_FUNC: case OP_FUNC:
AsFunctionPreamble(Node->Value.ID); AsFunctionPreamble(Node->Symbol);
AssembleTree(Node->Left, -1, Node->Operation); AssembleTree(Node->Left, -1, Node->Operation);
AsFunctionEpilogue(Node->Value.ID); AsFunctionEpilogue(Node->Symbol);
return -1; return -1;
} }
@ -107,17 +107,17 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case OP_SCALE: case OP_SCALE:
// We can (ab)use the powers of 2 to do // We can (ab)use the powers of 2 to do
// efficient scaling with bitshifting. // efficient scaling with bitshifting.
switch(Node->Value.Size) { switch(Node->Size) {
case 2: return AsShl(LeftVal, 1); case 2: return AsShl(LeftVal, 1);
case 4: return AsShl(LeftVal, 2); case 4: return AsShl(LeftVal, 2);
case 8: return AsShl(LeftVal, 3); case 8: return AsShl(LeftVal, 3);
default: default:
RightVal = AsLoad(Node->Value.Size); RightVal = AsLoad(Node->Size);
return AsMul(LeftVal, RightVal); return AsMul(LeftVal, RightVal);
} }
case OP_ADDRESS: case OP_ADDRESS:
return AsAddr(Node->Value.ID); return AsAddr(Node->Symbol);
case OP_DEREF: case OP_DEREF:
return Node->RVal ? AsDeref(LeftVal, Node->Left->ExprType) : LeftVal; 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) if(Node->Right == NULL)
Die("Fault in assigning a null rvalue"); 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) { switch(Node->Right->Operation) {
case REF_IDENT: case REF_IDENT:
if(Symbols[Node->Right->Value.ID].Storage == SC_LOCAL) if(Node->Right->Symbol->Storage == SC_LOCAL)
return AsStrLocalVar(LeftVal, Node->Right->Value.ID); return AsStrLocalVar(Node->Right->Symbol, LeftVal);
else else
return AsStrGlobalVar(LeftVal, Node->Right->Value.ID); return AsStrGlobalVar(Node->Right->Symbol, LeftVal);
case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType); case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType);
default: DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation); 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); return LeftVal; //AsWiden(LeftVal, Node->Left->ExprType, Node->ExprType);
case OP_RET: case OP_RET:
printf("\tReturning from %s, %d\n", Symbols[Node->Value.ID].Name, Node->Value.ID); printf("\tReturning from %s\n", Node->Symbol->Name);
AsReturn(LeftVal, CurrentFunction); AsReturn(FunctionEntry, LeftVal);
return -1; return -1;
/* case OP_EQUAL: /* case OP_EQUAL:
@ -181,18 +181,18 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
case REF_IDENT: 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); //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(Node->RVal || ParentOp == OP_DEREF) {
if(Symbols[Node->Value.ID].Storage == SC_LOCAL || Symbols[Node->Value.ID].Storage == SC_PARAM) if(Node->Symbol->Storage == SC_LOCAL || Node->Symbol->Storage == SC_PARAM)
return AsLdLocalVar(Node->Value.ID, Node->Operation); return AsLdLocalVar(Node->Symbol, Node->Operation);
else else
return AsLdGlobalVar(Node->Value.ID, Node->Operation); return AsLdGlobalVar(Node->Symbol, Node->Operation);
} else } else
return -1; return -1;
case TERM_INTLITERAL: case TERM_INTLITERAL:
return AsLoad(Node->Value.IntValue); return AsLoad(Node->IntValue);
case TERM_STRLITERAL: case TERM_STRLITERAL:
return AsLoadString(Node->Value.ID); return AsLoadString(Node->IntValue);
case OP_PRINT: case OP_PRINT:
AssemblerPrint(LeftVal); AssemblerPrint(LeftVal);
@ -220,16 +220,16 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) {
return AsShiftRight(LeftVal, RightVal); return AsShiftRight(LeftVal, RightVal);
case OP_POSTINC: case OP_POSTINC:
return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_POSTDEC: case OP_POSTDEC:
return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_PREINC: case OP_PREINC:
return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_PREDEC: case OP_PREDEC:
return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); return AsLdGlobalVar(Node->Symbol, Node->Operation);
case OP_BOOLNOT: case OP_BOOLNOT:
return AsBooleanNOT(LeftVal); return AsBooleanNOT(LeftVal);
@ -473,225 +473,217 @@ int AsShl(int Register, int Val) {
return Register; return Register;
} }
int AsLdGlobalVar(int ID, int Operation) { int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation) {
int Reg = RetrieveRegister(); 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) { int TypeSize = PrimitiveSize(Entry->Type);
case RET_CHAR: switch(TypeSize) {
case 1:
switch(Operation) { switch(Operation) {
case OP_PREINC: 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: 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) { switch(Operation) {
case OP_POSTINC: 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: 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; break;
case RET_INT: case 4:
switch(Operation) { switch(Operation) {
case OP_PREINC: 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: 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) { switch(Operation) {
case OP_POSTINC: 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: 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; break;
case RET_LONG: case 8:
case PTR_CHAR:
case PTR_INT:
case PTR_LONG:
case PTR_VOID:
switch(Operation) { switch(Operation) {
case OP_PREINC: 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: 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) { switch(Operation) {
case OP_POSTINC: 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: 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; break;
default: default:
DieMessage("Bad type for loading", TypeNames[Symbols[ID].Type]); DieMessage("Bad type for loading", TypeNames(Entry->Type));
} }
return Reg; return Reg;
} }
int AsStrGlobalVar(int Register, int ID) { int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register) {
printf("\tStoring contents of %s into %s, type %d, globally: ID %d\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type, ID); printf("\tStoring contents of %s into %s, type %d, globally:\n", Registers[Register], Entry->Name, Entry->Type);
switch(Symbols[ID].Type) { int TypeSize = PrimitiveSize(Entry->Type);
case RET_CHAR: switch(TypeSize) {
case 1:
// movzbq zeroes, then moves a byte into the quad register // 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; break;
case RET_INT: case 4:
fprintf(OutputFile, "\tmovl\t%s, %s(\%%rip)\n", DoubleRegisters[Register], Symbols[ID].Name); fprintf(OutputFile, "\tmovl\t%s, %s(\%%rip)\n", DoubleRegisters[Register], Entry->Name);
break; break;
case RET_LONG: case 8:
case PTR_CHAR: fprintf(OutputFile, "\tmovq\t%s, %s(%%rip)\n", Registers[Register], Entry->Name);
case PTR_INT:
case PTR_LONG:
case PTR_VOID:
fprintf(OutputFile, "\tmovq\t%s, %s(%%rip)\n", Registers[Register], Symbols[ID].Name);
break; break;
default: default:
DieMessage("Bad type for saving", TypeNames[Symbols[ID].Type]); DieMessage("Bad type for saving", TypeNames(Entry->Type));
} }
return Register; return Register;
} }
int AsLdLocalVar(int ID, int Operation) { int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation) {
int Reg = RetrieveRegister(); int Reg = RetrieveRegister();
printf("\tStoring the var at %d's contents into %s, locally\n", Symbols[ID].SinkOffset, Registers[Reg]); printf("\tStoring the var at %d's contents into %s, locally\n", Entry->SinkOffset, Registers[Reg]);
switch(Symbols[ID].Type) { int TypeSize = PrimitiveSize(Entry->Type);
case RET_CHAR: switch(TypeSize) {
case 1:
switch(Operation) { switch(Operation) {
case OP_PREINC: 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: 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) { switch(Operation) {
case OP_POSTINC: 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: 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; break;
case RET_INT: case 4:
switch(Operation) { switch(Operation) {
case OP_PREINC: 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: 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) { switch(Operation) {
case OP_POSTINC: 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: 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; break;
case RET_LONG: case 8:
case PTR_CHAR:
case PTR_INT:
case PTR_LONG:
case PTR_VOID:
switch(Operation) { switch(Operation) {
case OP_PREINC: 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: 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) { switch(Operation) {
case OP_POSTINC: 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: 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; break;
default: default:
DieMessage("Bad type for loading", TypeNames[Symbols[ID].Type]); DieMessage("Bad type for loading", TypeNames(Entry->Type));
} }
return Reg; return Reg;
} }
int AsStrLocalVar(int Register, int ID) { int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register) {
printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type); printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Entry->Name, Entry->Type);
switch(Symbols[ID].Type) { int TypeSize = PrimitiveSize(Entry->Type);
case RET_CHAR: switch(TypeSize) {
case 1:
// movzbq zeroes, then moves a byte into the quad register // 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; break;
case RET_INT: case 4:
fprintf(OutputFile, "\tmovl\t%s, %d(\%%rbp)\n", DoubleRegisters[Register], Symbols[ID].SinkOffset); fprintf(OutputFile, "\tmovl\t%s, %d(\%%rbp)\n", DoubleRegisters[Register], Entry->SinkOffset);
break; break;
case RET_LONG: case 8:
case PTR_CHAR: fprintf(OutputFile, "\tmovq\t%s, %d(%%rbp)\n", Registers[Register], Entry->SinkOffset);
case PTR_INT:
case PTR_LONG:
case PTR_VOID:
fprintf(OutputFile, "\tmovq\t%s, %d(%%rbp)\n", Registers[Register], Symbols[ID].SinkOffset);
break; break;
default: default:
DieMessage("Bad type for saving", TypeNames[Symbols[ID].Type]); DieMessage("Bad type for saving", TypeNames(Entry->Type));
} }
return Register; return Register;
} }
int AsAddr(int ID) { int AsAddr(struct SymbolTableEntry* Entry) {
int Register = RetrieveRegister(); 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; return Register;
} }
int AsDeref(int Reg, int Type) { int AsDeref(int Reg, int Type) {
int DestSize = PrimitiveSize(ValueAt(Type));
printf("\tDereferencing %s\n", Registers[Reg]); printf("\tDereferencing %s\n", Registers[Reg]);
switch(Type) { switch(DestSize) {
case PTR_CHAR: case 1:
fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], Registers[Reg]); fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], Registers[Reg]);
break; break;
case PTR_INT: case 2:
case PTR_LONG: 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]); fprintf(OutputFile, "\tmovq\t(%s), %s\n", Registers[Reg], Registers[Reg]);
break; break;
default: default:
@ -719,22 +711,22 @@ int AsStrDeref(int Register1, int Register2, int Type) {
return Register1; return Register1;
} }
void AsGlobalSymbol(int ID) { void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
int TypeSize; int TypeSize;
TypeSize = PrimitiveSize(Symbols[ID].Type); TypeSize = PrimitiveSize(Entry->Type);
fprintf(OutputFile, "\t.data\n" fprintf(OutputFile, "\t.data\n"
"\t.globl\t%s\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) { switch(TypeSize) {
case 1: fprintf(OutputFile, "\t.byte\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", Symbols[ID].Name); break; case 4: fprintf(OutputFile, "\t.long\t0\r\n", Entry->Name); break;
case 8: fprintf(OutputFile, "\t.quad\t0\r\n", Symbols[ID].Name); break; case 8: fprintf(OutputFile, "\t.quad\t0\r\n", Entry->Name); break;
default: DieDecimal("Unknown type in AsNewSymbol", TypeSize); break; default: DieDecimal("Unknown type in AsNewSymbol", TypeSize); break;
} }
} }
@ -746,13 +738,13 @@ int AsCallWrapper(struct ASTNode* Node) {
while(CompositeTree) { while(CompositeTree) {
Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation); Register = AssembleTree(CompositeTree->Right, -1, CompositeTree->Operation);
AsCopyArgs(Register, CompositeTree->Value.Size); AsCopyArgs(Register, CompositeTree->Size);
if(Args == 0) Args = CompositeTree->Value.Size; if(Args == 0) Args = CompositeTree->Size;
DeallocateAllRegisters(); DeallocateAllRegisters();
CompositeTree = CompositeTree->Left; CompositeTree = CompositeTree->Left;
} }
return AsCall(Node->Value.ID, Args); return AsCall(Node->Symbol, Args);
} }
void AsCopyArgs(int Register, int Position) { 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(); 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]); 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) if(Args > 4)
fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4)); fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4));
@ -779,11 +771,11 @@ int AsCall(int FuncID, int Args) {
return OutRegister; 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: case RET_CHAR:
fprintf(OutputFile, "\tmovzbl\t%s, %%eax\n", ByteRegisters[Register]); fprintf(OutputFile, "\tmovzbl\t%s, %%eax\n", ByteRegisters[Register]);
break; break;
@ -797,11 +789,11 @@ int AsReturn(int Register, int FuncID) {
break; break;
default: 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); OutputFile);
} }
void AsFunctionPreamble(int FunctionID) { void AsFunctionPreamble(struct SymbolTableEntry* Entry) {
char* Name = Symbols[FunctionID].Name; char* Name = Entry->Name;
int ParamOffset = 0, ParamReg = 9; struct SymbolTableEntry* Param, *Local;
int ParamOffset = 0, ParamReg = 9, ParamCount = 0;
LocalVarOffset = 4; // Prepare parameters LocalVarOffset = 4; // Prepare parameters
@ -943,24 +936,19 @@ void AsFunctionPreamble(int FunctionID) {
int LoopIndex; int LoopIndex;
// If we have parameters, move them to the last 4 registers // If we have parameters, move them to the last 4 registers
for(LoopIndex = SYMBOLS - 1; LoopIndex > CurrentLocal; LoopIndex--) { for(Param = Entry->Start, ParamCount = 1; Param != NULL; Param = Param->NextSymbol, ParamCount++) {
if(Symbols[LoopIndex].Storage != SC_PARAM) if(ParamCount > 4) { // We only have 4 argument registers
break; Param->SinkOffset = ParamOffset;
if(LoopIndex < SYMBOLS - 4) // We only have 4 argument registers ParamOffset += 8;
break; }
Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type); Entry->SinkOffset = AsCalcOffset(Param->Type);
AsStrLocalVar(ParamReg--, LoopIndex); AsStrLocalVar(Param, ParamReg--);
} }
// If we have more parameters, move them to the stack // If we have more parameters, move them to the stack
for(; LoopIndex > CurrentLocal; LoopIndex--) { for(Local = Locals; Local != NULL; Local = Local->NextSymbol) {
if(Symbols[LoopIndex].Storage == SC_PARAM) { Local->SinkOffset = AsCalcOffset(Local->Type);
Symbols[LoopIndex].SinkOffset = ParamOffset + 16;
ParamOffset += 8;
} else {
Symbols[LoopIndex].SinkOffset = AsCalcOffset(Symbols[LoopIndex].Type);
}
} }
// With all the parameters on the stack, we can allocate the shadow space // 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) { void AsFunctionEpilogue(struct SymbolTableEntry* Entry) {
AsLabel(Symbols[FunctionID].EndLabel); AsLabel(Entry->EndLabel);
fprintf(OutputFile, fprintf(OutputFile,
"\tpopq\t%%rbp\n" "\tpopq\t%%rbp\n"

View File

@ -12,27 +12,27 @@ static int GenerateSrg() {
return srgId++; return srgId++;
} }
void DumpTree(struct ASTNode* node, int level) { void DumpTree(struct ASTNode* Node, int level) {
int Lfalse, Lstart, Lend; int Lfalse, Lstart, Lend;
// Handle weirdo loops and conditions first. // Handle weirdo loops and conditions first.
switch(node->Operation) { switch(Node->Operation) {
case OP_IF: case OP_IF:
Lfalse = GenerateSrg(); Lfalse = GenerateSrg();
for(int i = 0; i < level; i++) for(int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "IF"); fprintf(stdout, "IF");
if(node->Right) { if(Node->Right) {
Lend = GenerateSrg(); Lend = GenerateSrg();
fprintf(stdout, ", end label %d", Lend); fprintf(stdout, ", end label %d", Lend);
} }
fprintf(stdout, "\n"); fprintf(stdout, "\n");
DumpTree(node->Left, level + 2); DumpTree(Node->Left, level + 2);
DumpTree(node->Middle, level + 2); DumpTree(Node->Middle, level + 2);
if(node->Right) if(Node->Right)
DumpTree(node->Right, level + 2); DumpTree(Node->Right, level + 2);
return; return;
case OP_LOOP: case OP_LOOP:
@ -41,28 +41,28 @@ void DumpTree(struct ASTNode* node, int level) {
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "LOOP starts at %d\n", Lstart); fprintf(stdout, "LOOP starts at %d\n", Lstart);
Lend = GenerateSrg(); Lend = GenerateSrg();
DumpTree(node->Left, level + 2); DumpTree(Node->Left, level + 2);
DumpTree(node->Right, level + 2); DumpTree(Node->Right, level + 2);
return; return;
} }
// If current node is a compound, we treat it as if we didn't just enter a loop. // 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; level = -2;
if(node->Left) if(Node->Left)
DumpTree(node->Left, level + 2); DumpTree(Node->Left, level + 2);
if(node->Right) if(Node->Right)
DumpTree(node->Right, level + 2); DumpTree(Node->Right, level + 2);
// The meat of this operation! // The meat of this operation!
for(int i = 0; i < level; i++) for(int i = 0; i < level; i++)
fprintf(stdout, " "); fprintf(stdout, " ");
switch (node->Operation){ switch (Node->Operation){
case OP_COMP: fprintf(stdout, "\n\n"); return; 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_ADD: fprintf(stdout, "OP_ADD\n"); return;
case OP_SUBTRACT: fprintf(stdout, "OP_SUBTRACT\n"); return; case OP_SUBTRACT: fprintf(stdout, "OP_SUBTRACT\n"); return;
case OP_MULTIPLY: fprintf(stdout, "OP_MULTIPLY\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_GREAT: fprintf(stdout, "OP_GREAT\n"); return;
case OP_LESSE: fprintf(stdout, "OP_LESSE\n"); return; case OP_LESSE: fprintf(stdout, "OP_LESSE\n"); return;
case OP_GREATE: fprintf(stdout, "OP_GREATE\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_INTLITERAL: fprintf(stdout, "TERM_INTLITERAL %d\n", Node->IntValue); return;
case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", node->Value.IntValue); return; case TERM_STRLITERAL: fprintf(stdout, "TERM_STRLITERAL rval L%d\n", Node->IntValue); return;
case REF_IDENT: case REF_IDENT:
if(node->RVal) if(Node->RVal)
fprintf(stdout, "REF_IDENT rval %s\n", Symbols[node->Value.ID].Name); fprintf(stdout, "REF_IDENT rval %s\n", Node->Symbol->Name);
else else
fprintf(stdout, "REF_IDENT %s\n", Symbols[node->Value.ID].Name); fprintf(stdout, "REF_IDENT %s\n", Node->Symbol->Name);
return; return;
case OP_ASSIGN: fprintf(stdout, "OP_ASSIGN\n"); return; case OP_ASSIGN: fprintf(stdout, "OP_ASSIGN\n"); return;
case OP_WIDEN: fprintf(stdout, "OP_WIDEN\n"); return; case OP_WIDEN: fprintf(stdout, "OP_WIDEN\n"); return;
case OP_RET: fprintf(stdout, "OP_RET\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_CALL: fprintf(stdout, "OP_CALL %s\n", Node->Symbol->Name); return;
case OP_ADDRESS: fprintf(stdout, "OP_ADDRESS %s\n", Symbols[node->Value.ID].Name); return; case OP_ADDRESS: fprintf(stdout, "OP_ADDRESS %s\n", Node->Symbol->Name); return;
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->Size)); return;
case OP_BOOLOR: fprintf(stdout, "OP_BOOLOR\n"); return; case OP_BOOLOR: fprintf(stdout, "OP_BOOLOR\n"); return;
case OP_BOOLAND: fprintf(stdout, "OP_BOOLAND\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; 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

@ -10,7 +10,7 @@
#include <errno.h> #include <errno.h>
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[] = { char* TokenNames[] = {
"End of file", "End of file",
@ -76,9 +76,6 @@ char* TokenNames[] = {
"Return keyword" "Return keyword"
}; };
char* TypeNames[9] = { "none", "char", "int", "long", "void", "charptr", "intptr", "longptr", "voidptr"};
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
/* Line = 1; /* Line = 1;
Overread = '\n'; Overread = '\n';

View File

@ -52,33 +52,35 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
struct ASTNode* Left, struct ASTNode* Left,
struct ASTNode* Middle, struct ASTNode* Middle,
struct ASTNode* Right, struct ASTNode* Right,
struct SymbolTableEntry* Symbol,
int IntValue) { int IntValue) {
struct ASTNode* Node; struct ASTNode* Node;
Node = (struct ASTNode*) malloc(sizeof(struct ASTNode)); Node = (struct ASTNode*) malloc(sizeof(struct ASTNode));
if(!Node) { if(!Node)
fprintf(stderr, "Unable to allocate node!"); Die("Unable to allocate node!");
exit(1);
}
Node->Operation = Operation; Node->Operation = Operation;
Node->ExprType = Type; Node->ExprType = Type;
Node->Left = Left; Node->Left = Left;
Node->Middle = Middle; Node->Middle = Middle;
Node->Right = Right; Node->Right = Right;
Node->Value.IntValue = IntValue; Node->Symbol = Symbol;
Node->IntValue = IntValue;
return Node; return Node;
} }
struct ASTNode* ConstructASTLeaf(int Operation, int Type, int IntValue) { struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue) {
return ConstructASTNode(Operation, Type, NULL, NULL, NULL, IntValue); return ConstructASTNode(Operation, Type, NULL, NULL, NULL, Symbol, 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) {
return ConstructASTNode(Operation, Type, Left, NULL, NULL, IntValue); return ConstructASTNode(Operation, Type, Left, NULL, NULL, Symbol, IntValue);
} }
@ -116,15 +118,15 @@ struct ASTNode* ParsePrimary(void) {
case LI_INT: case LI_INT:
if((CurrentToken.value >= 0) && (CurrentToken.value < 256)) 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 else
Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, CurrentToken.value); Node = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, CurrentToken.value);
break; break;
case LI_STR: case LI_STR:
ID = AsNewString(CurrentIdentifier); ID = AsNewString(CurrentIdentifier);
Node = ConstructASTLeaf(TERM_STRLITERAL, PTR_CHAR, ID); Node = ConstructASTLeaf(TERM_STRLITERAL, PointerTo(RET_CHAR), NULL, ID);
break; break;
case TY_IDENTIFIER: 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); //printf("\tAssigning variable: %s value %d\n", Symbols[FindSymbol(CurrentIdentifier)].Name, RightNode->Value.IntValue);
// LeftNode holds the target, the target variable in this case // LeftNode holds the target, the target variable in this case
printf("\t\tAssigning variable: %s\n", Symbols[LeftNode->Value.ID].Name); printf("\t\tAssigning variable: %s\n", LeftNode->Symbol->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);
LeftTemp = LeftNode; LeftTemp = LeftNode;
LeftNode = RightNode; LeftNode = RightNode;
@ -253,7 +254,7 @@ struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence) {
if(RightTemp != NULL) if(RightTemp != NULL)
RightNode = RightTemp; // ConstructASTBranch(RightType, LeftNode->ExprType, RightNode, 0); 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; NodeType = CurrentToken.type;
if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) { if(NodeType == LI_SEMIC || NodeType == LI_RPARE || NodeType == LI_RBRAS) {
LeftNode->RVal = 1; LeftNode->RVal = 1;
@ -367,17 +368,17 @@ int ParseAST(struct ASTNode* Node) {
struct ASTNode* CallFunction() { struct ASTNode* CallFunction() {
struct ASTNode* Tree; struct ASTNode* Tree;
int FuncID; struct SymbolTableEntry* Function;
//TODO: Test structural type! //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); DieMessage("Undeclared function", CurrentIdentifier);
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
Tree = GetExpressionList(); Tree = GetExpressionList();
Tree = ConstructASTBranch(OP_CALL, Symbols[FuncID].Type, Tree, FuncID); Tree = ConstructASTBranch(OP_CALL, Function->Type, Tree, Function, 0);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
@ -392,7 +393,7 @@ struct ASTNode* GetExpressionList() {
Child = ParsePrecedenceASTNode(0); Child = ParsePrecedenceASTNode(0);
Count++; 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) { switch(CurrentToken.type) {
case LI_COM: case LI_COM:
@ -475,7 +476,7 @@ struct ASTNode* ParseCompound() {
if(Left == NULL) if(Left == NULL)
Left = Tree; Left = Tree;
else 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) { if(CurrentToken.type == LI_RBRAC) {
@ -507,7 +508,7 @@ void ParseGlobals() {
printf("\tParsing function"); printf("\tParsing function");
Tree = ParseFunction(Type); Tree = ParseFunction(Type);
if(Tree) { 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); AssembleTree(Tree, -1, 0);
FreeLocals(); FreeLocals();
} else { } else {

View File

@ -8,44 +8,38 @@
#include <Data.h> #include <Data.h>
int PointerTo(int Type) { int PointerTo(int Type) {
//Type = Type + 1; if((Type & 0xf) == 0xf)
printf("\t\tPointerising a %s\n", TypeNames[Type]); DieDecimal("Unrecognized type in pointerisation", Type);
// As it stands, the conversion between printf("\t\tPointerising a %s\n", TypeNames(Type));
// RET and PTR is +4. return (Type + 1);
// 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;
} }
int ValueAt(int Type) { 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! //TODO: this is still bullshittery!
if(Type >= PTR_CHAR && Type <= PTR_VOID) { if((Type & 0xf) == 0x0)
printf("\t\t\tDereference of %s is %s.\r\n", TypeNames[Type], TypeNames[Type - 4]); DieDecimal("Unrecognized type in defererencing", Type);
return Type - 4; return (Type - 1);
} else {
DieDecimal("Unable to dereference type", Type);
}
return -1;
} }
int ParseOptionalPointer() { int ParseOptionalPointer() {
int Type; int Type;
// TODO: THIS IS WRONG AND SHOULD NOT EXIST
if(CurrentToken.type >= TY_CHAR && CurrentToken.type <= TY_VOID) { switch(CurrentToken.type) {
Type = CurrentToken.type - (TY_CHAR - RET_CHAR); case TY_VOID:
printf("\t\tConverting a %s token to a %s type.\n", TokenNames[CurrentToken.type], TypeNames[Type]); Type = RET_VOID;
} else { 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); DieDecimal("Illegal type for pointerisation", CurrentToken.type);
} }
// Recursively scan more *s // Recursively scan more *s
@ -66,13 +60,13 @@ int ParseOptionalPointer() {
struct ASTNode* AccessArray() { struct ASTNode* AccessArray() {
struct ASTNode* LeftNode, *RightNode; struct ASTNode* LeftNode, *RightNode;
int ID; struct SymbolTableEntry* Entry;
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier); 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); 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]); //printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]);
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
//printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]); //printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]);
@ -84,12 +78,12 @@ struct ASTNode* AccessArray() {
if(!TypeIsInt(RightNode->ExprType)) if(!TypeIsInt(RightNode->ExprType))
Die("Array index is not integer"); 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); 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"); 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"); printf("\tArray Access constructed\r\n");
return LeftNode; return LeftNode;
} }

View File

@ -8,21 +8,21 @@
#include <Data.h> #include <Data.h>
#include <stdbool.h> #include <stdbool.h>
static int ReadParameters(int FuncID) { static int ReadParameters(struct SymbolTableEntry* FunctionSymbol) {
int TokenType, ParamCount = 0, ProtoParamCount, ParamIndex; int TokenType, ParamCount = 0;
ParamIndex = FuncID + 1; struct SymbolTableEntry* PrototypePointer = NULL;
if(ParamIndex) // If FuncID > -1 (If the function exists)
ProtoParamCount = Symbols[FuncID].Length; // Set the prototype length
if(FunctionSymbol != NULL)
PrototypePointer = FunctionSymbol->Start;
while(CurrentToken.type != LI_RPARE) { while(CurrentToken.type != LI_RPARE) {
TokenType = ParseOptionalPointer(); TokenType = ParseOptionalPointer();
VerifyToken(TY_IDENTIFIER, "identifier"); VerifyToken(TY_IDENTIFIER, "identifier");
if(ParamIndex) { if(PrototypePointer != NULL) {
if(TokenType != Symbols[FuncID].Type) if(TokenType != PrototypePointer->Type)
DieDecimal("Function paramater of invalid type at index", ParamCount + 1); DieDecimal("Function paramater of invalid type at index", ParamCount + 1);
ParamIndex++; PrototypePointer=PrototypePointer->NextSymbol;
} else { } else {
BeginVariableDeclaration(TokenType, SC_PARAM); BeginVariableDeclaration(TokenType, SC_PARAM);
} }
@ -39,8 +39,8 @@ static int ReadParameters(int FuncID) {
} }
} }
if((FuncID != -1) && (ParamCount != ProtoParamCount)) if((FunctionSymbol != NULL) && (ParamCount != FunctionSymbol->Length))
DieMessage("Invalid number of parameters in prototyped function", Symbols[FuncID].Name); DieMessage("Invalid number of parameters in prototyped function", FunctionSymbol->Name);
return ParamCount; return ParamCount;
} }
@ -49,76 +49,85 @@ static int ReadParameters(int FuncID) {
* Handles the declaration of a type of a variable. * Handles the declaration of a type of a variable.
* int newVar; * 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. * unique, non-keyword identifier.
* *
* It then stores this variable into the symbol table. * It then stores this variable into the symbol table,
* * and returns the new item.
* //TODO: Assemble this into the symbol table.
* //TODO: int i = 5;
* *
*/ */
void BeginVariableDeclaration(int Type, int Scope) { struct SymbolTableEntry* BeginVariableDeclaration(int Type, int Scope) {
int ID; struct SymbolTableEntry* Symbol = NULL;
printf("type: %s\n", TypeNames[Type]);
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) { if(CurrentToken.type == LI_LBRAS) {
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
//Type = Type - 2;
if(CurrentToken.type == LI_INT) { if(CurrentToken.type == LI_INT) {
printf("Adding array %s that is %d x %s.\r\n", CurrentIdentifier, CurrentToken.value, TypeNames[Type]); switch(Scope) {
if(Scope == SC_LOCAL) case SC_GLOBAL:
Die("Local arrays are not supported"); Symbol = AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 1, 0);
else break;
AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 0, CurrentToken.value); case SC_LOCAL:
case SC_PARAM:
Die("Local arrays are unimplemented");
}
} }
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
VerifyToken(LI_RBRAS, "]"); VerifyToken(LI_RBRAS, "]");
} else { } else {
printf("Adding var %s that is a %s\r\n", CurrentIdentifier, TypeNames[Type]); Symbol = AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 1, 0);
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);
}
} }
//VerifyToken(LI_SEMIC, ";"); return Symbol;
} }
struct ASTNode* ParseFunction(int Type) { struct ASTNode* ParseFunction(int Type) {
struct ASTNode* Tree; struct ASTNode* Tree;
struct ASTNode* FinalStatement; struct ASTNode* FinalStatement;
struct SymbolTableEntry* OldFunction, *NewFunction = NULL;
int SymbolSlot, BreakLabel, ParamCount, ID; int SymbolSlot, BreakLabel, ParamCount, ID;
if((ID = FindSymbol(CurrentIdentifier)) != -1) if((OldFunction = FindSymbol(CurrentIdentifier)) != NULL)
if(Symbols[ID].Structure != ST_FUNC) if(OldFunction->Storage != ST_FUNC)
ID = -1; OldFunction = NULL;
if(OldFunction == NULL) {
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;
BreakLabel = NewLabel(); BreakLabel = NewLabel();
NewFunction = AddSymbol(CurrentIdentifier, Type, ST_FUNC, SC_GLOBAL, BreakLabel, 0);
} }
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
ParamCount = ReadParameters(ID); ParamCount = ReadParameters(OldFunction);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
if(ID == -1) { if(NewFunction) {
Symbols[SymbolSlot].Length = ParamCount; NewFunction->Elements = ParamCount;
ID = SymbolSlot; NewFunction->Start = Params;
OldFunction = NewFunction;
} }
Params = ParamsEnd = NULL;
if(CurrentToken.type == LI_SEMIC) { if(CurrentToken.type == LI_SEMIC) {
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
return NULL; 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(); Tree = ParseCompound();
@ -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* ReturnStatement() {
struct ASTNode* Tree; 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"); Die("Attempt to return from void function");
VerifyToken(KW_RETURN, "return"); VerifyToken(KW_RETURN, "return");
@ -162,7 +171,7 @@ struct ASTNode* ReturnStatement() {
FunctionType = Symbols[CurrentFunction].Type; FunctionType = Symbols[CurrentFunction].Type;
*/ */
Tree = MutateType(Tree, Symbols[CurrentFunction].Type, 0); Tree = MutateType(Tree, FunctionEntry->Type, 0);
if(Tree == NULL) if(Tree == NULL)
Die("Returning a value of incorrect type for function"); Die("Returning a value of incorrect type for function");
@ -171,9 +180,9 @@ struct ASTNode* ReturnStatement() {
Tree = ConstructASTBranch(ReturnType, FunctionType, Tree, 0); 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! VerifyToken(LI_RPARE, ")"); // TODO: OPTIONALISE!
@ -245,7 +254,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)
Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, 0); Condition = ConstructASTBranch(OP_BOOLCONV, Condition->ExprType, Condition, NULL, 0);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
@ -256,7 +265,7 @@ struct ASTNode* IfStatement() {
False = ParseCompound(); 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() { struct ASTNode* WhileStatement() {
@ -269,13 +278,13 @@ struct ASTNode* WhileStatement() {
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, NULL, 0);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
Body = ParseCompound(); 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() { struct ASTNode* ForStatement() {
@ -298,7 +307,7 @@ struct ASTNode* ForStatement() {
Condition = ParsePrecedenceASTNode(0); Condition = ParsePrecedenceASTNode(0);
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, NULL, 0);
VerifyToken(LI_SEMIC, ";"); VerifyToken(LI_SEMIC, ";");
@ -308,13 +317,13 @@ struct ASTNode* ForStatement() {
Body = ParseCompound(); Body = ParseCompound();
// We need to be able to skip over the body and the postop, so we group them together. // 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, // 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 // 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 // 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) { struct ASTNode* PrintStatement(void) {
@ -333,9 +342,9 @@ struct ASTNode* PrintStatement(void) {
DieDecimal("Attempting to print an invalid type:", RightType); DieDecimal("Attempting to print an invalid type:", RightType);
if(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); //ParseAST(Tree);
@ -345,7 +354,7 @@ struct ASTNode* PrintStatement(void) {
struct ASTNode* PostfixStatement() { struct ASTNode* PostfixStatement() {
struct ASTNode* Tree; struct ASTNode* Tree;
int ID; struct SymbolTableEntry* Entry;
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
@ -364,8 +373,7 @@ struct ASTNode* PostfixStatement() {
// There's no guarantees that the variable is in // There's no guarantees that the variable is in
// the symbol table, though. // the symbol table, though.
ID = FindSymbol(CurrentIdentifier); if((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_VAR)
if(ID == -1 || Symbols[ID].Structure != ST_VAR)
DieMessage("Unknown Variable", CurrentIdentifier); DieMessage("Unknown Variable", CurrentIdentifier);
// Here we check for postincrement and postdecrement. // Here we check for postincrement and postdecrement.
@ -373,14 +381,14 @@ struct ASTNode* PostfixStatement() {
switch(CurrentToken.type) { switch(CurrentToken.type) {
case PPMM_PLUS: case PPMM_PLUS:
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
Tree = ConstructASTLeaf(OP_POSTINC, Symbols[ID].Type, ID); Tree = ConstructASTLeaf(OP_POSTINC, Entry->Type, Entry, 0);
break; break;
case PPMM_MINUS: case PPMM_MINUS:
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
Tree = ConstructASTLeaf(OP_POSTDEC, Symbols[ID].Type, ID); Tree = ConstructASTLeaf(OP_POSTDEC, Entry->Type, Entry, 0);
break; break;
default: default:
Tree = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID); Tree = ConstructASTLeaf(REF_IDENT, Entry->Type, Entry, 0);
} }
return Tree; return Tree;
@ -395,21 +403,21 @@ struct ASTNode* PrefixStatement() {
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
Tree = PrefixStatement(); Tree = PrefixStatement();
Tree->RVal = 1; Tree->RVal = 1;
Tree = ConstructASTBranch(OP_BOOLNOT, Tree->ExprType, Tree, 0); Tree = ConstructASTBranch(OP_BOOLNOT, Tree->ExprType, Tree, NULL, 0);
break; break;
case BIT_NOT: case BIT_NOT:
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
Tree = PrefixStatement(); Tree = PrefixStatement();
Tree->RVal = 1; Tree->RVal = 1;
Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, 0); Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, NULL, 0);
break; break;
case AR_MINUS: case AR_MINUS:
Tokenise(&CurrentToken); Tokenise(&CurrentToken);
Tree = PrefixStatement(); Tree = PrefixStatement();
Tree = ConstructASTBranch(OP_NEGATE, Tree->ExprType, Tree, 0); Tree = ConstructASTBranch(OP_NEGATE, Tree->ExprType, Tree, NULL, 0);
break; break;
case PPMM_PLUS: case PPMM_PLUS:
@ -418,7 +426,7 @@ struct ASTNode* PrefixStatement() {
if(Tree->Operation != REF_IDENT) if(Tree->Operation != REF_IDENT)
Die("++ not followed by identifier"); Die("++ not followed by identifier");
Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, 0); Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, NULL, 0);
break; break;
case PPMM_MINUS: case PPMM_MINUS:
@ -428,7 +436,7 @@ struct ASTNode* PrefixStatement() {
if(Tree->Operation != REF_IDENT) if(Tree->Operation != REF_IDENT)
Die("-- not followed by identifier"); Die("-- not followed by identifier");
Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, 0); Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, NULL, 0);
break; break;
case BIT_AND: case BIT_AND:
@ -453,7 +461,7 @@ struct ASTNode* PrefixStatement() {
if(Tree->Operation != REF_IDENT && Tree->Operation != OP_DEREF) if(Tree->Operation != REF_IDENT && Tree->Operation != OP_DEREF)
Die("* must be followed by another * or an identifier."); 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; break;
default: default:

View File

@ -7,105 +7,138 @@
#include <Defs.h> #include <Defs.h>
#include <Data.h> #include <Data.h>
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. * Find the position of a symbol in a given symbol table.
* @Return the index into the symbol table if found, * @param Name: The string name of the symbol
* -1 if not found. * @param List: The linked list to search in.
* Does not care about differentiating local or global. * @return the list if found,
* It will only be consistent. * NULL if no found.
*/ */
int FindSymbol(char* Symbol) {
int Res; static struct SymbolTableEntry* SearchList(char* Name, struct SymbolTableEntry* List) {
// Prioritise local vars for(; List != NULL; List = List->NextSymbol)
if((Res = FindSymbolImpl(Symbol, SC_LOCAL)) == -1) if((List->Name != NULL) && !strcmp(Name, List->Name))
// Fallback to global vars. return (List);
return FindSymbolImpl(Symbol, SC_GLOBAL); return NULL;
return Res;
} }
/* /*
* Append a new entry to the table of global symbols. * Search all the tables for a symbol.
* @Return the index to the new entry * 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;
if((Pos = (CurrentGlobal++)) >= CurrentLocal) {
printf("%d:%d\r\n", CurrentGlobal, CurrentLocal);
Die("Too many Global symbols");
}
return Pos;
}
/*
* 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?
*/ */
static int NewLocalSymbol() { struct SymbolTableEntry* FindSymbol(char* Symbol) {
int Pos; struct SymbolTableEntry* Node;
if((Pos = (CurrentLocal--)) <= CurrentGlobal)
Die("Too many Local symbols");
return Pos; if(CurrentFunction) {
Node = SearchList(Symbol, FunctionEntry->Start);
if(Node)
return Node;
}
Node = SearchList(Symbol, Locals);
if(Node)
return Node;
return SearchList(Symbol, Globals);
} }
/* /*
* Reset the local counter on functions. * 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
*/
struct SymbolTableEntry* FindLocal(char* Symbol) {
struct SymbolTableEntry* Node;
if(FunctionEntry) {
Node = SearchList(Symbol, FunctionEntry->Start);
if(Node)
return Node;
}
return SearchList(Symbol, Locals);
}
/*
* 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() { 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 Name: The string representing the name of the symbol.
* @param Type: The return type in terms of DataTypes enum values. * @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 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 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 label # to jump to to exit the function or array, where appropriate.
* @param Length: The size of the struct/array in units of 1xbase * 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; int SinkOffset = 0;
if((TableSlot = FindSymbolImpl(Name, Storage)) != -1) 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(); TableSlot = NewLocalSymbol();
SinkOffset = AsCalcOffset(Type); SinkOffset = AsCalcOffset(Type);
break; 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); /* // NOTE: Generating global symbol names must happen AFTER the name and type are declared.
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.
switch(Storage) { switch(Storage) {
case SC_GLOBAL: case SC_GLOBAL:
printf("\tCreating new global symbol %s into slot %d\r\n", Name, TableSlot); 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; break;
case SC_LOCAL: case SC_LOCAL:
break; break;
} } */
//printf("Adding new variable %s of type %s to the table at %d\n", CurrentIdentifier, Types[Type], TableSlot); //printf("Adding new variable %s of type %s to the table at %d\n", CurrentIdentifier, Types[Type], TableSlot);
return TableSlot; return Node;
} }

View File

@ -9,15 +9,11 @@
int TypeIsInt(int Type) { int TypeIsInt(int Type) {
if(Type == RET_CHAR || Type == RET_INT || Type == RET_LONG) return ((Type & 0xf) == 0);
return 1;
return 0;
} }
int TypeIsPtr(int Type) { int TypeIsPtr(int Type) {
if(Type == PTR_VOID || Type == PTR_CHAR || Type == PTR_INT || Type == PTR_LONG) return ((Type & 0xf) != 0);
return 1;
return 0;
} }
/* /*
@ -33,10 +29,32 @@ int TypeIsPtr(int Type) {
*/ */
int PrimitiveSize(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) 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 // 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)); RightSize = PrimitiveSize(ValueAt(RightType));
if(RightSize > 1) if(RightSize > 1)
return ConstructASTBranch(OP_SCALE, RightType, Tree, RightSize); return ConstructASTBranch(OP_SCALE, RightType, Tree, NULL, RightSize);
} }
} }