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:
parent
a52779e379
commit
eb118db872
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
278
src/Assembler.c
278
src/Assembler.c
|
@ -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"
|
||||||
|
|
52
src/Dump.c
52
src/Dump.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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';
|
||||||
|
|
43
src/Parser.c
43
src/Parser.c
|
@ -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 {
|
||||||
|
|
|
@ -8,45 +8,39 @@
|
||||||
#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;
|
||||||
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
|
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
|
// Recursively scan more *s
|
||||||
// This makes things like:
|
// This makes things like:
|
||||||
|
@ -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;
|
||||||
}
|
}
|
154
src/Statements.c
154
src/Statements.c
|
@ -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:
|
||||||
|
|
200
src/Symbols.c
200
src/Symbols.c
|
@ -7,105 +7,138 @@
|
||||||
#include <Defs.h>
|
#include <Defs.h>
|
||||||
#include <Data.h>
|
#include <Data.h>
|
||||||
|
|
||||||
static int GlobalSymbols = 0;
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
int FindSymbolImpl(char* Symbol, int Storage) {
|
/*
|
||||||
int Ind;
|
* 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct SymbolTableEntry* FindSymbol(char* Symbol) {
|
||||||
|
struct SymbolTableEntry* Node;
|
||||||
|
|
||||||
for(Ind = (Storage == SC_GLOBAL /* Are we global scope? */
|
if(CurrentFunction) {
|
||||||
? 0 /* If so, start from the beginning */
|
Node = SearchList(Symbol, FunctionEntry->Start);
|
||||||
: CurrentLocal + 1 /* Else, go from the start of the local block */
|
if(Node)
|
||||||
);
|
return Node;
|
||||||
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;
|
Node = SearchList(Symbol, Locals);
|
||||||
|
if(Node)
|
||||||
|
return Node;
|
||||||
|
|
||||||
|
return SearchList(Symbol, Globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the position of a symbol in the symbol table.
|
* An override for FindSymbol.
|
||||||
* @Return the index into the symbol table if found,
|
* Searches only the parameters and local variables.
|
||||||
* -1 if not found.
|
* @param Symbol: The string name of the symbol to search for.
|
||||||
* Does not care about differentiating local or global.
|
* @return a pointer to the node if found, else NULL
|
||||||
* It will only be consistent.
|
|
||||||
*/
|
*/
|
||||||
int FindSymbol(char* Symbol) {
|
struct SymbolTableEntry* FindLocal(char* Symbol) {
|
||||||
int Res;
|
struct SymbolTableEntry* Node;
|
||||||
// Prioritise local vars
|
|
||||||
if((Res = FindSymbolImpl(Symbol, SC_LOCAL)) == -1)
|
|
||||||
// Fallback to global vars.
|
|
||||||
return FindSymbolImpl(Symbol, SC_GLOBAL);
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if(FunctionEntry) {
|
||||||
* Append a new entry to the table of global symbols.
|
Node = SearchList(Symbol, FunctionEntry->Start);
|
||||||
* @Return the index to the new entry
|
if(Node)
|
||||||
*
|
return Node;
|
||||||
* 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;
|
return SearchList(Symbol, Locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append a new entry to the table of local (function-local) symbols.
|
* An override for FindSymbol.
|
||||||
* @Return the index to the new entry
|
* 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
|
||||||
*
|
*
|
||||||
* 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* FindGlobal(char* Symbol) {
|
||||||
int Pos;
|
return SearchList(Symbol, Globals);
|
||||||
if((Pos = (CurrentLocal--)) <= CurrentGlobal)
|
|
||||||
Die("Too many Local symbols");
|
|
||||||
|
|
||||||
return Pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset the local counter on functions.
|
* 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;
|
||||||
}
|
}
|
40
src/Types.c
40
src/Types.c
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user