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 SYMBOLS 1024
extern_ struct SymbolTable Symbols[SYMBOLS];
extern_ struct SymbolTableEntry* Globals, *GlobalsEnd;
extern_ struct SymbolTableEntry* Locals, *LocalsEnd;
extern_ struct SymbolTableEntry* Params, *ParamsEnd;
extern_ bool OptDumpTree;
extern_ bool OptKeepAssembly;
@ -26,12 +28,12 @@ extern_ bool OptVerboseOutput;
extern_ char* OutputFileName;
extern_ char* CurrentASMFile, *CurrentObjectFile;
extern_ int TypeSizes[9];
extern_ char* TypeNames[9];
extern_ int TypeSizes[5];
extern_ char* TokenNames[];
extern_ int CurrentFunction;
extern_ struct SymbolTableEntry* FunctionEntry;
extern_ int Line;
extern_ int Overread;

View File

@ -174,11 +174,12 @@ struct ASTNode {
struct ASTNode* Left;
struct ASTNode* Middle;
struct ASTNode* Right;
struct SymbolTableEntry* Symbol;
union {
int Size; // OP_SCALE's linear representation
int IntValue; // TERM_INTLIT's Value
int ID; // LV_IDENT's Symbols[] index.
} Value;
};
};
struct Token {
@ -191,14 +192,25 @@ struct Token {
* assorted goodies.
*/
struct SymbolTable {
struct SymbolTableEntry {
char* Name;
int Type; // An entry in DataTypes, referring to the type of this data
struct SymbolTableEntry* CompositeType; // A pointer to the start of a Symbol Table list that represents a certain Composite type
int Structure; // An entry in StructureType - metadata on how to process the data
int EndLabel; // The number of the label to jump to, in order to exit this function (if applicable)
int Length; // The length of the symbol in units of 1 element -- the size of an array, for example.
int Storage; // The scope of this symbol - decides when it is discarded.
int SinkOffset; // How many times must we sink the rbp to get to this symbol in the stack?
union {
int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable)
int Length; // For an array - The length of the symbol in units of 1 element -- the size of an array, for example.
int IntValue; // For an enum - The value of an Enum entry
};
union {
int SinkOffset; // For a variable - How many times must we sink the rbp to get to this symbol in the stack?
int Elements; // For a function - How many parameters?
};
struct SymbolTableEntry* NextSymbol; // The next symbol in a list
struct SymbolTableEntry* Start; // The first member in a list
};
enum StorageScope {
@ -212,22 +224,23 @@ enum StorageScope {
/*
* The primitive data types for the language
* //TODO: Move back into TokenTypes
* The types of data being held in memory.
* The lowest 4 bits of these enum values
* encode a nested pointer type.
*
* This meaning, a single enum can hold
* ****************int types.
* Should be enough for everyone, right?
*/
enum DataTypes {
RET_NONE, // No return type. Literal void.
RET_CHAR, // "char" type keyword
RET_INT, // "int" type keyword
RET_LONG, // "long" type keyword
RET_VOID, // "void" type keyword
// Pointer types
PTR_CHAR,
PTR_INT,
PTR_LONG,
PTR_VOID,
RET_NONE, // No return type. Literal void.
RET_CHAR = 16, // "char" type keyword
RET_INT = 32, // "int" type keyword
RET_LONG = 48, // "long" type keyword
RET_VOID = 64, // "void" type keyword
DAT_STRUCT = 80, // Struct Data
DAT_UNION, // Union Data
};
/*
@ -278,6 +291,8 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation);
int TypeIsInt(int Type);
int TypeIsPtr(int Type);
char* TypeNames(int Type);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * S Y N T A X T R E E * * * * * *
@ -288,11 +303,12 @@ struct ASTNode* ConstructASTNode(int Operation, int Type,
struct ASTNode* Left,
struct ASTNode* Middle,
struct ASTNode* Right,
struct SymbolTableEntry* Symbol,
int IntValue);
struct ASTNode* ConstructASTLeaf(int Operation, int Type, int IntValue);
struct ASTNode* ConstructASTLeaf(int Operation, int Type, struct SymbolTableEntry* Symbol, int IntValue);
struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, int IntValue);
struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left, struct SymbolTableEntry* Symbol, int IntValue);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
@ -336,11 +352,17 @@ struct ASTNode* PrintStatement(void);
* * * * * * S Y M B O L T A B L E * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
int FindSymbol(char* Symbol);
struct SymbolTableEntry* FindSymbol(char* Symbol);
struct SymbolTableEntry* FindLocal(char* Symbol);
struct SymbolTableEntry* FindGlobal(char* Symbol);
int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length);
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node);
void FreeLocals();
void ClearTables();
struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * C O N T R O L S T A T U S * * * *
@ -375,19 +397,19 @@ int AsMul(int Left, int Right);
int AsSub(int Left, int Right);
int AsDiv(int Left, int Right);
int AsLdGlobalVar(int ID, int Operation);
int AsLdLocalVar(int ID, int Operation);
int AsStrGlobalVar(int Register, int ID);
int AsStrLocalVar(int Register, int ID);
int AsLdGlobalVar(struct SymbolTableEntry* Entry, int Operation);
int AsLdLocalVar(struct SymbolTableEntry* Entry, int Operation);
int AsStrGlobalVar(struct SymbolTableEntry* Entry, int Register);
int AsStrLocalVar(struct SymbolTableEntry* Entry, int Register);
int AsCalcOffset(int Type);
void AsNewStackFrame();
int AsDeref(int Reg, int Type);
int AsStrDeref(int Register1, int Register2, int Type);
int AsAddr(int ID);
int AsAddr(struct SymbolTableEntry* Entry);
void AsGlobalSymbol(int ID);
void AsGlobalSymbol(struct SymbolTableEntry* Entry);
int AsNewString(char* Value);
@ -420,25 +442,25 @@ void AsLabel(int Label);
int AsShl(int Register, int Val);
int AsReturn(int Register, int FuncID);
int AsReturn(struct SymbolTableEntry* Entry, int Register);
int AsCallWrapper(struct ASTNode* Node);
void AsCopyArgs(int Register, int Position);
int AsCall(int Register, int FuncID);
int AsCall(struct SymbolTableEntry* Entry, int Args);
int AsWhile(struct ASTNode* Node);
void AssemblerPrint(int Register);
void AssemblerPreamble();
void AsFunctionPreamble(int ID);
void AsFunctionEpilogue(int ID);
void AsFunctionPreamble(struct SymbolTableEntry* Entry);
void AsFunctionEpilogue(struct SymbolTableEntry* Entry);
/* * * * * * * * * * * * * * * * * * * * * * *
* * * * D E C L A R A T I O N * * * *
* * * * * * * * * * * * * * * * * * * * * * */
void BeginVariableDeclaration(int Type, int Scope);
struct SymbolTableEntry* BeginVariableDeclaration(int Type, int Scope);
struct ASTNode* ParseIdentifier(void);
struct ASTNode* IfStatement();

View File

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

View File

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

View File

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

View File

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

View File

@ -8,45 +8,39 @@
#include <Data.h>
int PointerTo(int Type) {
//Type = Type + 1;
printf("\t\tPointerising a %s\n", TypeNames[Type]);
// As it stands, the conversion between
// RET and PTR is +4.
// TODO: if we add types, increase this number
// TODO: Make this a proper translation table
// TODO: More checks! This can go wrong easily!
if(Type >= RET_CHAR && Type <= RET_VOID) {
return Type + (PTR_CHAR - RET_CHAR);
} else {
DieDecimal("Unable to create a pointer to the desired type", Type);
}
return -1;
if((Type & 0xf) == 0xf)
DieDecimal("Unrecognized type in pointerisation", Type);
printf("\t\tPointerising a %s\n", TypeNames(Type));
return (Type + 1);
}
int ValueAt(int Type) {
printf("\t\tDereferencing a %s\n", TypeNames[Type]);
printf("\t\tDereferencing a %s\n", TypeNames(Type));
//TODO: this is still bullshittery!
if(Type >= PTR_CHAR && Type <= PTR_VOID) {
printf("\t\t\tDereference of %s is %s.\r\n", TypeNames[Type], TypeNames[Type - 4]);
return Type - 4;
} else {
DieDecimal("Unable to dereference type", Type);
}
return -1;
if((Type & 0xf) == 0x0)
DieDecimal("Unrecognized type in defererencing", Type);
return (Type - 1);
}
int ParseOptionalPointer() {
int Type;
// TODO: THIS IS WRONG AND SHOULD NOT EXIST
if(CurrentToken.type >= TY_CHAR && CurrentToken.type <= TY_VOID) {
Type = CurrentToken.type - (TY_CHAR - RET_CHAR);
printf("\t\tConverting a %s token to a %s type.\n", TokenNames[CurrentToken.type], TypeNames[Type]);
} else {
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
switch(CurrentToken.type) {
case TY_VOID:
Type = RET_VOID;
break;
case TY_CHAR:
Type = RET_CHAR;
break;
case TY_INT:
Type = RET_INT;
break;
case TY_LONG:
Type = RET_LONG;
break;
default:
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
}
// Recursively scan more *s
// This makes things like:
@ -66,13 +60,13 @@ int ParseOptionalPointer() {
struct ASTNode* AccessArray() {
struct ASTNode* LeftNode, *RightNode;
int ID;
struct SymbolTableEntry* Entry;
printf("\tAccessing array %s as requested\r\n", CurrentIdentifier);
if ((ID = FindSymbol(CurrentIdentifier)) == -1 || Symbols[ID].Structure != ST_ARR)
if ((Entry = FindSymbol(CurrentIdentifier)) == NULL || Entry->Structure != ST_ARR)
DieMessage("Accessing undeclared array", CurrentIdentifier);
LeftNode = ConstructASTLeaf(OP_ADDRESS, Symbols[ID].Type, ID);
LeftNode = ConstructASTLeaf(OP_ADDRESS, Entry->Type, Entry, 0);
//printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]);
Tokenise(&CurrentToken);
//printf("\t\tCurrent token: %s\r\n", TokenNames[CurrentToken.type]);
@ -84,12 +78,12 @@ struct ASTNode* AccessArray() {
if(!TypeIsInt(RightNode->ExprType))
Die("Array index is not integer");
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", TypeNames[RightNode->ExprType], TypeNames[LeftNode->ExprType]);
printf("\t\tPreparing types - RightNode of type %s must be mutated to LeftNode type %s\r\n", (RightNode->ExprType), TypeNames(LeftNode->ExprType));
RightNode = MutateType(RightNode, LeftNode->ExprType, OP_ADD);
LeftNode = ConstructASTNode(OP_ADD, Symbols[ID].Type, LeftNode, NULL, RightNode, 0);
LeftNode = ConstructASTNode(OP_ADD, Entry->Type, LeftNode, NULL, RightNode, NULL, 0);
printf("\tAccessArray: Preparing LeftNode for dereference.\r\n");
LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, 0);
LeftNode = ConstructASTBranch(OP_DEREF, ValueAt(LeftNode->ExprType), LeftNode, NULL, 0);
printf("\tArray Access constructed\r\n");
return LeftNode;
}

View File

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

View File

@ -7,105 +7,138 @@
#include <Defs.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? */
? 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;
}
if(CurrentFunction) {
Node = SearchList(Symbol, FunctionEntry->Start);
if(Node)
return Node;
}
return -1;
Node = SearchList(Symbol, Locals);
if(Node)
return Node;
return SearchList(Symbol, Globals);
}
/*
* Find the position of a symbol in the symbol table.
* @Return the index into the symbol table if found,
* -1 if not found.
* Does not care about differentiating local or global.
* It will only be consistent.
* 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
*/
int FindSymbol(char* Symbol) {
int Res;
// Prioritise local vars
if((Res = FindSymbolImpl(Symbol, SC_LOCAL)) == -1)
// Fallback to global vars.
return FindSymbolImpl(Symbol, SC_GLOBAL);
return Res;
}
struct SymbolTableEntry* FindLocal(char* Symbol) {
struct SymbolTableEntry* Node;
/*
* Append a new entry to the table of global symbols.
* @Return the index to the new entry
*
* 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");
if(FunctionEntry) {
Node = SearchList(Symbol, FunctionEntry->Start);
if(Node)
return Node;
}
return Pos;
return SearchList(Symbol, Locals);
}
/*
* Append a new entry to the table of local (function-local) symbols.
* @Return the index to the new entry
* 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
*
* 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() {
int Pos;
if((Pos = (CurrentLocal--)) <= CurrentGlobal)
Die("Too many Local symbols");
return Pos;
struct SymbolTableEntry* FindGlobal(char* Symbol) {
return SearchList(Symbol, Globals);
}
/*
* 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() {
CurrentLocal = SYMBOLS - 1;
Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL;
}
/*
* Reset all tables.
*/
void ClearTables() {
Globals = GlobalsEnd = NULL;
Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL;
}
/*
* Add a symbol to the tables, and set all the metadata.
* Create a symbol item, and set all the metadata.
* @param Name: The string representing the name of the symbol.
* @param Type: The return type in terms of DataTypes enum values.
* @param Structure: The type of symbol this is, in terms of StructureType enum.
* @param Storage: The storage scope of this symbol. For functions this is always SC_GLOBAL (for now). Vars and Arrays can be GLOBAL or SC_LOCAL.
* @param EndLabel: The label # to jump to to exit the function or array, where appropriate.
* @param Length: The size of the struct/array in units of 1xbase
* @param Length: The label # to jump to to exit the function or array, where appropriate.
* The size of the struct/array in units of 1xbase
*
* @return The ID in the symbol table that now represents this symbol.
* @return The SymbolTableEntry* pointer that corresponds to this newly constructed node.
*/
int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length) {
struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Storage, int Length, int SinkOffset) {
int TableSlot;
/* int TableSlot;
int SinkOffset = 0;
if((TableSlot = FindSymbolImpl(Name, Storage)) != -1)
@ -130,17 +163,32 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in
TableSlot = NewLocalSymbol();
SinkOffset = AsCalcOffset(Type);
break;
} */
struct SymbolTableEntry* Node =
(struct SymbolTableEntry*) malloc(sizeof(struct SymbolTableEntry));
Node->Name = strdup(Name);
Node->Type = Type;
Node->Structure = Structure;
Node->Storage = Storage;
Node->Length = Length;
Node->SinkOffset = SinkOffset;
switch(Storage) {
case SC_GLOBAL:
AppendSymbol(&Globals, &GlobalsEnd, Node);
if(Structure != ST_FUNC) AsGlobalSymbol(Node);
break;
case SC_LOCAL:
AppendSymbol(&Locals, &LocalsEnd, Node);
break;
case SC_PARAM:
AppendSymbol(&Params, &ParamsEnd, Node);
break;
}
Symbols[TableSlot].Name = strdup(Name);
Symbols[TableSlot].Type = Type;
Symbols[TableSlot].Structure = Structure;
Symbols[TableSlot].Storage = Storage;
Symbols[TableSlot].Length = Length;
Symbols[TableSlot].SinkOffset = SinkOffset;
Symbols[TableSlot].EndLabel = EndLabel;
// NOTE: Generating global symbol names must happen AFTER the name and type are declared.
/* // NOTE: Generating global symbol names must happen AFTER the name and type are declared.
switch(Storage) {
case SC_GLOBAL:
printf("\tCreating new global symbol %s into slot %d\r\n", Name, TableSlot);
@ -151,8 +199,8 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in
break;
case SC_LOCAL:
break;
}
} */
//printf("Adding new variable %s of type %s to the table at %d\n", CurrentIdentifier, Types[Type], TableSlot);
return TableSlot;
return Node;
}

View File

@ -9,15 +9,11 @@
int TypeIsInt(int Type) {
if(Type == RET_CHAR || Type == RET_INT || Type == RET_LONG)
return 1;
return 0;
return ((Type & 0xf) == 0);
}
int TypeIsPtr(int Type) {
if(Type == PTR_VOID || Type == PTR_CHAR || Type == PTR_INT || Type == PTR_LONG)
return 1;
return 0;
return ((Type & 0xf) != 0);
}
/*
@ -33,10 +29,32 @@ int TypeIsPtr(int Type) {
*/
int PrimitiveSize(int Type) {
if(Type < RET_NONE || Type > PTR_VOID)
DieDecimal("Checking size of bad data type", Type);
return TypeSizes[Type];
if(TypeIsPtr(Type)) return 8;
switch(Type) {
case RET_CHAR: return 1;
case RET_INT: return 4;
case RET_LONG: return 8;
default:
DieDecimal("Bad type in PrimitiveSize", Type);
}
return 0;
}
static char TypeBuffer[7];
char* TypeNames(int Type) {
switch(Type) {
case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break;
case RET_INT: memcpy(TypeBuffer, "Int ", 4); break;
case RET_LONG: memcpy(TypeBuffer, "Long", 4); break;
case RET_VOID: memcpy(TypeBuffer, "Void", 4); break;
default: DieDecimal("Bad size for printing", Type);
};
if(TypeIsPtr(Type)) memcpy((void*)((size_t) TypeBuffer + 4), "Ptr", 3);
else memcpy((void*)((size_t) TypeBuffer + 4), " ", 3);
return TypeBuffer;
}
/*
@ -180,7 +198,7 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
*/
if(RightSize > LeftSize)
return ConstructASTBranch(OP_WIDEN, RightType, Tree, 0);
return ConstructASTBranch(OP_WIDEN, RightType, Tree, NULL, 0);
}
// Left branch pointers are compatible if we're not doing operations
@ -206,7 +224,7 @@ struct ASTNode* MutateType(struct ASTNode* Tree, int RightType, int Operation) {
RightSize = PrimitiveSize(ValueAt(RightType));
if(RightSize > 1)
return ConstructASTBranch(OP_SCALE, RightType, Tree, RightSize);
return ConstructASTBranch(OP_SCALE, RightType, Tree, NULL, RightSize);
}
}