Small fixes, complete refactor

This commit is contained in:
Curle 2021-01-22 01:01:53 +00:00
parent e19a945934
commit 72358aed9f
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
6 changed files with 94 additions and 43 deletions

View File

@ -295,6 +295,7 @@ int TypeIsInt(int Type);
int TypeIsPtr(int Type); int TypeIsPtr(int Type);
char* TypeNames(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 * * * * * * * * * * * * * * * * * * P A R S I N G * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//struct ASTNode* ParseNewASTNode(void);
//struct ASTNode* ParseAdditiveASTNode(void);
struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence); struct ASTNode* ParsePrecedenceASTNode(int PreviousTokenPrecedence);
//int ParseAST(struct ASTNode* Node);
struct ASTNode* ParsePrimary(void); struct ASTNode* ParsePrimary(void);
//void ParseStatements(void);
struct ASTNode* ParseStatement(void); struct ASTNode* ParseStatement(void);
struct ASTNode* PrefixStatement(); struct ASTNode* PrefixStatement();
struct ASTNode* PostfixStatement(); struct ASTNode* PostfixStatement();
@ -335,6 +332,7 @@ void ParseGlobals();
struct ASTNode* ParseFunction(int Type); struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound(); struct ASTNode* ParseCompound();
struct SymbolTableEntry* BeginStructDeclaration();
struct ASTNode* GetExpressionList(); struct ASTNode* GetExpressionList();
struct ASTNode* CallFunction(); struct ASTNode* CallFunction();
struct ASTNode* ReturnStatement(); struct ASTNode* ReturnStatement();
@ -394,6 +392,7 @@ int RetrieveRegister();
void DeallocateRegister(int Register); void DeallocateRegister(int Register);
int PrimitiveSize(int Type); int PrimitiveSize(int Type);
int AsAlignMemory(int Type, int Offset, int Direction);
int AsLoad(int Value); int AsLoad(int Value);
int AsAdd(int Left, int Right); int AsAdd(int Left, int Right);

View File

@ -317,6 +317,29 @@ int NewLabel(void) {
return id++; 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 // Assemble an If statement
int AsIf(struct ASTNode* Node) { int AsIf(struct ASTNode* Node) {
int FalseLabel, EndLabel; int FalseLabel, EndLabel;
@ -775,9 +798,12 @@ int AsStrDeref(int Register1, int Register2, int Type) {
// Assemble a global symbol (variable, struct, enum, function, string) // Assemble a global symbol (variable, struct, enum, function, string)
void AsGlobalSymbol(struct SymbolTableEntry* Entry) { 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" fprintf(OutputFile, "\t.data\n"
"\t.globl\t%s\n", "\t.globl\t%s\n",
@ -785,14 +811,15 @@ void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
fprintf(OutputFile, "%s:\n", Entry->Name); fprintf(OutputFile, "%s:\n", Entry->Name);
for(int i = 0; i < Entry->Length; i++) { switch(Size) {
switch(TypeSize) {
case 1: fprintf(OutputFile, "\t.byte\t0\r\n", Entry->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 4: fprintf(OutputFile, "\t.long\t0\r\n", Entry->Name); break;
case 8: fprintf(OutputFile, "\t.quad\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. // Assemble a function call, with all associated parameter bumping and stack movement.

View File

@ -367,7 +367,7 @@ void Tokenise() {
if(RejectedToken != NULL) { if(RejectedToken != NULL) {
Token = RejectedToken; Token = RejectedToken;
RejectedToken = NULL; RejectedToken = NULL;
return 1; return;
} }
Char = FindChar(); Char = FindChar();
@ -375,7 +375,7 @@ void Tokenise() {
switch(Char) { switch(Char) {
case EOF: case EOF:
Token->type = LI_EOF; Token->type = LI_EOF;
return 0; return;
case '+': case '+':
// + can be either "+" or "++". // + can be either "+" or "++".

View File

@ -424,7 +424,7 @@ struct ASTNode* ParseStatement(void) {
case TY_LONG: case TY_LONG:
case TY_INT: case TY_INT:
printf("\t\tNew Variable: %s\n", CurrentIdentifier); printf("\t\tNew Variable: %s\n", CurrentIdentifier);
Type = ParseOptionalPointer(); Type = ParseOptionalPointer(NULL);
VerifyToken(TY_IDENTIFIER, "ident"); VerifyToken(TY_IDENTIFIER, "ident");
BeginVariableDeclaration(Type, NULL, SC_LOCAL); BeginVariableDeclaration(Type, NULL, SC_LOCAL);
VerifyToken(LI_SEMIC, ";"); // TODO: single line assignment? VerifyToken(LI_SEMIC, ";"); // TODO: single line assignment?
@ -517,7 +517,7 @@ void ParseGlobals() {
while(1) { while(1) {
printf("New definition incoming..\r\n\n"); printf("New definition incoming..\r\n\n");
Type = ParseOptionalPointer(); Type = ParseOptionalPointer(NULL);
//TODO: converge pathways on this block? //TODO: converge pathways on this block?
if(CurrentToken.type == KW_FUNC) { if(CurrentToken.type == KW_FUNC) {

View File

@ -34,12 +34,14 @@ static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Stor
PrototypePointer = FunctionSymbol->Start; PrototypePointer = FunctionSymbol->Start;
while(CurrentToken.type != LI_RPARE) { while(CurrentToken.type != LI_RPARE) {
TokenType = ParseOptionalPointer(); TokenType = ParseOptionalPointer(FunctionSymbol);
VerifyToken(TY_IDENTIFIER, "identifier"); VerifyToken(TY_IDENTIFIER, "identifier");
printf("\tReading a new element: %s of type %d\n", CurrentIdentifier, TokenType);
if(PrototypePointer != NULL) { if(PrototypePointer != NULL) {
if(TokenType != PrototypePointer->Type) 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; PrototypePointer=PrototypePointer->NextSymbol;
} else { } else {
BeginVariableDeclaration(TokenType, Composite, Storage); BeginVariableDeclaration(TokenType, Composite, Storage);
@ -93,9 +95,9 @@ struct SymbolTableEntry* BeginStructDeclaration() {
Composite = AddSymbol(CurrentIdentifier, DAT_STRUCT, 0, SC_STRUCT, 0, 0, NULL); Composite = AddSymbol(CurrentIdentifier, DAT_STRUCT, 0, SC_STRUCT, 0, 0, NULL);
Tokenise(); Tokenise();
printf("Reading a struct declaration..\n");
ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAS); ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAC);
VerifyToken(LI_RBRAS, "]"); VerifyToken(LI_RBRAC, "}");
Composite->Start = StructMembers; Composite->Start = StructMembers;
StructMembers = StructMembersEnd = NULL; StructMembers = StructMembersEnd = NULL;
@ -195,7 +197,7 @@ struct ASTNode* ParseFunction(int Type) {
} }
VerifyToken(LI_LPARE, "("); VerifyToken(LI_LPARE, "(");
ParamCount = ReadParameters(OldFunction); ParamCount = ReadDeclarationList(OldFunction, SC_GLOBAL, LI_RPARE);
VerifyToken(LI_RPARE, ")"); VerifyToken(LI_RPARE, ")");
if(NewFunction) { if(NewFunction) {

View File

@ -7,11 +7,29 @@
#include <Defs.h> #include <Defs.h>
#include <Data.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) { int TypeIsInt(int Type) {
return ((Type & 0xf) == 0); 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) { int TypeIsPtr(int Type) {
return ((Type & 0xf) != 0); return ((Type & 0xf) != 0);
} }
@ -20,12 +38,6 @@ int TypeIsPtr(int Type) {
* Turn a token type into its appropriate * Turn a token type into its appropriate
* primitive type. * primitive type.
* *
* This is where we do redirections like:
* short -> s16
* long -> s64
* int -> s32
* char -> u8
*
*/ */
int PrimitiveSize(int Type) { int PrimitiveSize(int Type) {
@ -41,8 +53,28 @@ int PrimitiveSize(int Type) {
return 0; 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]; static char TypeBuffer[7];
/*
* Get the name of the input Type as a string.
*/
char* TypeNames(int Type) { char* TypeNames(int Type) {
switch(Type) { switch(Type) {
case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break; case RET_CHAR: memcpy(TypeBuffer, "Char", 4); break;
@ -58,21 +90,12 @@ char* TypeNames(int Type) {
} }
/* /*
* Given two types, determine if they are compatible. * Determine if two types are compatible.
* * A left char and a right int are compatible, as the char will fit into the int.
* Depending on the value of STRICT, it will try to * The left char will need to be widened for assignment, however.
* 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.
* *
* If strict is set, you can only widen the Left to the Right.
* If strict is false, any widening is valid.
* *
*/ */