Small fixes, complete refactor
This commit is contained in:
parent
e19a945934
commit
72358aed9f
|
@ -295,6 +295,7 @@ int TypeIsInt(int Type);
|
|||
int TypeIsPtr(int Type);
|
||||
|
||||
char* TypeNames(int Type);
|
||||
int TypeSize(int Type, struct SymbolTableEntry* Composite);
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
@ -318,14 +319,10 @@ struct ASTNode* ConstructASTBranch(int Operation, int Type, struct ASTNode* Left
|
|||
* * * * * * * * * P A R S I N G * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
//struct ASTNode* ParseNewASTNode(void);
|
||||
//struct ASTNode* ParseAdditiveASTNode(void);
|
||||
struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence);
|
||||
|
||||
//int ParseAST(struct ASTNode* Node);
|
||||
|
||||
struct ASTNode* ParsePrimary(void);
|
||||
//void ParseStatements(void);
|
||||
struct ASTNode* ParseStatement(void);
|
||||
struct ASTNode* PrefixStatement();
|
||||
struct ASTNode* PostfixStatement();
|
||||
|
@ -335,6 +332,7 @@ void ParseGlobals();
|
|||
struct ASTNode* ParseFunction(int Type);
|
||||
struct ASTNode* ParseCompound();
|
||||
|
||||
struct SymbolTableEntry* BeginStructDeclaration();
|
||||
struct ASTNode* GetExpressionList();
|
||||
struct ASTNode* CallFunction();
|
||||
struct ASTNode* ReturnStatement();
|
||||
|
@ -394,6 +392,7 @@ int RetrieveRegister();
|
|||
void DeallocateRegister(int Register);
|
||||
|
||||
int PrimitiveSize(int Type);
|
||||
int AsAlignMemory(int Type, int Offset, int Direction);
|
||||
|
||||
int AsLoad(int Value);
|
||||
int AsAdd(int Left, int Right);
|
||||
|
|
|
@ -317,6 +317,29 @@ int NewLabel(void) {
|
|||
return id++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Align non-char types to a 4 byte alignment.
|
||||
* Chars need no alignment on x86_64.
|
||||
*
|
||||
* @param Type: The DataTypes representation of the data to align
|
||||
* @param Offset: The offset to align
|
||||
* @param Direction: The desired direction to move the address for alignment. 1 = up, -1 = down.
|
||||
* @return the new alignment
|
||||
*
|
||||
*/
|
||||
int AsAlignMemory(int Type, int Offset, int Direction) {
|
||||
switch(Type) {
|
||||
case RET_CHAR: return Offset;
|
||||
case RET_INT: case RET_LONG: break;
|
||||
default:
|
||||
DieDecimal("Unable to align type", Type);
|
||||
}
|
||||
|
||||
int Alignment = 4;
|
||||
Offset = (Offset + Direction * (Alignment-1)) & ~(Alignment-1);
|
||||
return (Offset);
|
||||
}
|
||||
|
||||
// Assemble an If statement
|
||||
int AsIf(struct ASTNode* Node) {
|
||||
int FalseLabel, EndLabel;
|
||||
|
@ -775,9 +798,12 @@ int AsStrDeref(int Register1, int Register2, int Type) {
|
|||
|
||||
// Assemble a global symbol (variable, struct, enum, function, string)
|
||||
void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
|
||||
int TypeSize;
|
||||
|
||||
TypeSize = PrimitiveSize(Entry->Type);
|
||||
if(Entry == NULL) return;
|
||||
if(Entry->Structure == ST_FUNC) return;
|
||||
|
||||
|
||||
int Size = TypeSize(Entry->Type, Entry->CompositeType);
|
||||
|
||||
fprintf(OutputFile, "\t.data\n"
|
||||
"\t.globl\t%s\n",
|
||||
|
@ -785,14 +811,15 @@ void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
|
|||
|
||||
fprintf(OutputFile, "%s:\n", Entry->Name);
|
||||
|
||||
for(int i = 0; i < Entry->Length; i++) {
|
||||
switch(TypeSize) {
|
||||
switch(Size) {
|
||||
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;
|
||||
}
|
||||
default:
|
||||
for(int i = 0; i < Size; i++)
|
||||
fprintf(OutputFile, "\t.byte\t0\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Assemble a function call, with all associated parameter bumping and stack movement.
|
||||
|
|
|
@ -367,7 +367,7 @@ void Tokenise() {
|
|||
if(RejectedToken != NULL) {
|
||||
Token = RejectedToken;
|
||||
RejectedToken = NULL;
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
Char = FindChar();
|
||||
|
@ -375,7 +375,7 @@ void Tokenise() {
|
|||
switch(Char) {
|
||||
case EOF:
|
||||
Token->type = LI_EOF;
|
||||
return 0;
|
||||
return;
|
||||
|
||||
case '+':
|
||||
// + can be either "+" or "++".
|
||||
|
|
|
@ -424,7 +424,7 @@ struct ASTNode* ParseStatement(void) {
|
|||
case TY_LONG:
|
||||
case TY_INT:
|
||||
printf("\t\tNew Variable: %s\n", CurrentIdentifier);
|
||||
Type = ParseOptionalPointer();
|
||||
Type = ParseOptionalPointer(NULL);
|
||||
VerifyToken(TY_IDENTIFIER, "ident");
|
||||
BeginVariableDeclaration(Type, NULL, SC_LOCAL);
|
||||
VerifyToken(LI_SEMIC, ";"); // TODO: single line assignment?
|
||||
|
@ -517,7 +517,7 @@ void ParseGlobals() {
|
|||
|
||||
while(1) {
|
||||
printf("New definition incoming..\r\n\n");
|
||||
Type = ParseOptionalPointer();
|
||||
Type = ParseOptionalPointer(NULL);
|
||||
|
||||
//TODO: converge pathways on this block?
|
||||
if(CurrentToken.type == KW_FUNC) {
|
||||
|
|
|
@ -34,12 +34,14 @@ static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Stor
|
|||
PrototypePointer = FunctionSymbol->Start;
|
||||
|
||||
while(CurrentToken.type != LI_RPARE) {
|
||||
TokenType = ParseOptionalPointer();
|
||||
TokenType = ParseOptionalPointer(FunctionSymbol);
|
||||
VerifyToken(TY_IDENTIFIER, "identifier");
|
||||
|
||||
printf("\tReading a new element: %s of type %d\n", CurrentIdentifier, TokenType);
|
||||
|
||||
if(PrototypePointer != NULL) {
|
||||
if(TokenType != PrototypePointer->Type)
|
||||
DieDecimal("Function paramater of invalid type at index", ParamCount + 1);
|
||||
DieDecimal("Function parameter of invalid type at index", ParamCount + 1);
|
||||
PrototypePointer=PrototypePointer->NextSymbol;
|
||||
} else {
|
||||
BeginVariableDeclaration(TokenType, Composite, Storage);
|
||||
|
@ -93,9 +95,9 @@ struct SymbolTableEntry* BeginStructDeclaration() {
|
|||
|
||||
Composite = AddSymbol(CurrentIdentifier, DAT_STRUCT, 0, SC_STRUCT, 0, 0, NULL);
|
||||
Tokenise();
|
||||
|
||||
ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAS);
|
||||
VerifyToken(LI_RBRAS, "]");
|
||||
printf("Reading a struct declaration..\n");
|
||||
ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAC);
|
||||
VerifyToken(LI_RBRAC, "}");
|
||||
|
||||
Composite->Start = StructMembers;
|
||||
StructMembers = StructMembersEnd = NULL;
|
||||
|
@ -195,7 +197,7 @@ struct ASTNode* ParseFunction(int Type) {
|
|||
}
|
||||
|
||||
VerifyToken(LI_LPARE, "(");
|
||||
ParamCount = ReadParameters(OldFunction);
|
||||
ParamCount = ReadDeclarationList(OldFunction, SC_GLOBAL, LI_RPARE);
|
||||
VerifyToken(LI_RPARE, ")");
|
||||
|
||||
if(NewFunction) {
|
||||
|
|
63
src/Types.c
63
src/Types.c
|
@ -7,11 +7,29 @@
|
|||
#include <Defs.h>
|
||||
#include <Data.h>
|
||||
|
||||
/*
|
||||
* Returns whether the input Type represents a raw integer type.
|
||||
* It works on the principles outlined in Pointers.c; the lowest
|
||||
* 4 bits indicate indirection.
|
||||
*
|
||||
* @param Type: The DataTypes representation to check
|
||||
* @return a boolean representing whether the input Type is a raw integer
|
||||
*/
|
||||
|
||||
int TypeIsInt(int Type) {
|
||||
return ((Type & 0xf) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the input Type has at least one level of indirection.
|
||||
* It works on the principles outlined in Pointers.c; the lowest 4 bits
|
||||
* indicate indirection.
|
||||
*
|
||||
* @param Type: The DataTypes representation to check
|
||||
* @return a boolean representing whether the input Type is a pointer
|
||||
*
|
||||
*/
|
||||
|
||||
int TypeIsPtr(int Type) {
|
||||
return ((Type & 0xf) != 0);
|
||||
}
|
||||
|
@ -20,12 +38,6 @@ int TypeIsPtr(int Type) {
|
|||
* Turn a token type into its appropriate
|
||||
* primitive type.
|
||||
*
|
||||
* This is where we do redirections like:
|
||||
* short -> s16
|
||||
* long -> s64
|
||||
* int -> s32
|
||||
* char -> u8
|
||||
*
|
||||
*/
|
||||
|
||||
int PrimitiveSize(int Type) {
|
||||
|
@ -41,8 +53,28 @@ int PrimitiveSize(int Type) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dynamically calculate the size of an object.
|
||||
* This was performed with an array previously, but the addition of
|
||||
* structs and enums makes that irrelevant.
|
||||
*
|
||||
*/
|
||||
|
||||
int TypeSize(int Type, struct SymbolTableEntry* Composite) {
|
||||
if(Type == DAT_STRUCT) return Composite->Length;
|
||||
return PrimitiveSize(Type);
|
||||
}
|
||||
|
||||
/*
|
||||
* A char buffer we can abuse for printing type names.
|
||||
* It needs to be 7 because that's 4 (long) + 3 (ptr), the longest
|
||||
* possible name right now.
|
||||
*/
|
||||
static char TypeBuffer[7];
|
||||
|
||||
/*
|
||||
* Get the name of the input Type as a string.
|
||||
*/
|
||||
char* TypeNames(int Type) {
|
||||
switch(Type) {
|
||||
case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break;
|
||||
|
@ -58,21 +90,12 @@ char* TypeNames(int Type) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Given two types, determine if they are compatible.
|
||||
*
|
||||
* Depending on the value of STRICT, it will try to
|
||||
* fit the right value into the left value.
|
||||
*
|
||||
* This is valid, for ie. a char into an int, as int is larger than char.
|
||||
* This is called widening the char.
|
||||
*
|
||||
* If STRICT is set, it will only allow widening the left to the right.
|
||||
* This means you cannot `char a; int b; b = 15000; a = b;`
|
||||
* As this would shrink the int and lose resolution.
|
||||
*
|
||||
* NOTE: THIS IS NOT THE DEFAULT BEHAVIOUR
|
||||
* By default, you CAN shrink an int into a char, a la shifting down.
|
||||
* Determine if two types are compatible.
|
||||
* A left char and a right int are compatible, as the char will fit into the int.
|
||||
* The left char will need to be widened for assignment, however.
|
||||
*
|
||||
* If strict is set, you can only widen the Left to the Right.
|
||||
* If strict is false, any widening is valid.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user