Implement unions and largest-element allocation

This commit is contained in:
Curle 2022-03-03 02:44:07 +00:00
parent 537246daae
commit 3717b310be
11 changed files with 86 additions and 30 deletions

View File

@ -20,7 +20,8 @@ extern_ struct SymbolTableEntry* Globals, * GlobalsEnd;
extern_ struct SymbolTableEntry* Locals, * LocalsEnd; extern_ struct SymbolTableEntry* Locals, * LocalsEnd;
extern_ struct SymbolTableEntry* Params, * ParamsEnd; extern_ struct SymbolTableEntry* Params, * ParamsEnd;
extern_ struct SymbolTableEntry* Structs, * StructsEnd; extern_ struct SymbolTableEntry* Structs, * StructsEnd;
extern_ struct SymbolTableEntry* StructMembers, * StructMembersEnd;
extern_ struct SymbolTableEntry* CompositeMembers, * CompositeMembersEnd;
extern_ struct SymbolTableEntry* Unions, * UnionsEnd; extern_ struct SymbolTableEntry* Unions, * UnionsEnd;
extern_ struct SymbolTableEntry* Enums, * EnumsEnd; extern_ struct SymbolTableEntry* Enums, * EnumsEnd;

View File

@ -96,7 +96,8 @@ enum TokenTypes {
KW_WHILE, KW_WHILE,
KW_FOR, KW_FOR,
KW_RETURN, KW_RETURN,
KW_STRUCT KW_STRUCT,
KW_UNION
}; };
/* /*
@ -219,6 +220,7 @@ struct SymbolTableEntry {
enum StorageScope { enum StorageScope {
SC_GLOBAL = 1, // Global Scope SC_GLOBAL = 1, // Global Scope
SC_STRUCT, // Struct Definitions SC_STRUCT, // Struct Definitions
SC_UNION, // Union Definitions
SC_ENUM, // Enum Definitions SC_ENUM, // Enum Definitions
SC_MEMBER, // The members of Structs or Enums SC_MEMBER, // The members of Structs or Enums
//SC_CLASS, // Class-local definitions //SC_CLASS, // Class-local definitions
@ -348,7 +350,7 @@ struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound(); struct ASTNode* ParseCompound();
struct SymbolTableEntry* BeginStructDeclaration(); struct SymbolTableEntry* BeginCompositeDeclaration(int Type);
struct ASTNode* GetExpressionList(); struct ASTNode* GetExpressionList();
@ -387,6 +389,8 @@ struct SymbolTableEntry* FindGlobal(char* Symbol);
struct SymbolTableEntry* FindStruct(char* Symbol); struct SymbolTableEntry* FindStruct(char* Symbol);
struct SymbolTableEntry* FindUnion(char* Symbol);
struct SymbolTableEntry* FindMember(char* Symbol); struct SymbolTableEntry* FindMember(char* Symbol);
void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node); void AppendSymbol(struct SymbolTableEntry** Head, struct SymbolTableEntry** Tail, struct SymbolTableEntry* Node);

View File

@ -799,7 +799,7 @@ int AsDeref(int Reg, int Type) {
printf("\tDereferencing %s\n", Registers[Reg]); printf("\tDereferencing %s\n", Registers[Reg]);
switch (DestSize) { switch (DestSize) {
case 1: case 1:
fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], ByteRegisters[Reg]); fprintf(OutputFile, "\tmovzbq\t(%s), %s\n", Registers[Reg], Registers[Reg]);
break; break;
case 2: case 2:
fprintf(OutputFile, "\tmovslq\t(%s), %s\n", Registers[Reg], DoubleRegisters[Reg]); fprintf(OutputFile, "\tmovslq\t(%s), %s\n", Registers[Reg], DoubleRegisters[Reg]);

View File

@ -338,6 +338,11 @@ static int ReadKeyword(char* Str) {
return KW_STRUCT; return KW_STRUCT;
break; break;
case 'u':
if(!strcmp(Str, "union"))
return KW_UNION;
break;
case 'v': case 'v':
if (!strcmp(Str, "void")) if (!strcmp(Str, "void"))
return TY_VOID; return TY_VOID;

View File

@ -87,6 +87,7 @@ char* ScopeNames[] = {
"INVALID", "INVALID",
"GLOBAL", "GLOBAL",
"STRUCT", "STRUCT",
"UNION",
"ENUM", "ENUM",
"MEMBER", "MEMBER",
"PARAMETER", "PARAMETER",

View File

@ -534,7 +534,7 @@ void ParseGlobals() {
// Structs are parsed fully in ParseOptionalPointer // Structs are parsed fully in ParseOptionalPointer
// TODO: FIX THAT!! // TODO: FIX THAT!!
if (Type == DAT_STRUCT && CurrentToken.type == LI_SEMIC) { if ((Type == DAT_STRUCT || Type == DAT_UNION) && CurrentToken.type == LI_SEMIC) {
Tokenise(); Tokenise();
continue; continue;
} }

View File

@ -94,7 +94,11 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
break; break;
case KW_STRUCT: case KW_STRUCT:
Type = DAT_STRUCT; Type = DAT_STRUCT;
*Composite = BeginStructDeclaration(); *Composite = BeginCompositeDeclaration(Type);
break;
case KW_UNION:
Type = DAT_UNION;
*Composite = BeginCompositeDeclaration(Type);
break; break;
default: default:
DieDecimal("Illegal type for pointerisation", CurrentToken.type); DieDecimal("Illegal type for pointerisation", CurrentToken.type);
@ -175,13 +179,13 @@ struct ASTNode* AccessMember(bool Deref) {
if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL) if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
DieMessage("Undeclared variable", CurrentIdentifier); DieMessage("Undeclared variable", CurrentIdentifier);
if (Deref && CompositeVar->Type != PointerTo(DAT_STRUCT)) if (Deref && (CompositeVar->Type != PointerTo(DAT_STRUCT) && CompositeVar->Type != PointerTo(DAT_UNION)))
DieMessage("Undeclared struct", CurrentIdentifier); DieMessage("Undeclared struct", CurrentIdentifier);
if (!Deref && CompositeVar->Type != DAT_STRUCT) if (!Deref && (CompositeVar->Type != DAT_STRUCT && CompositeVar->Type != DAT_UNION))
DieMessage("Undeclared struct", CurrentIdentifier); DieMessage("Undeclared struct", CurrentIdentifier);
if (Deref) if (Deref)
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(DAT_STRUCT), CompositeVar, 0); LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(CompositeVar->Type), CompositeVar, 0);
else else
LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0); LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0);
@ -193,14 +197,14 @@ struct ASTNode* AccessMember(bool Deref) {
VerifyToken(TY_IDENTIFIER, "identifier"); VerifyToken(TY_IDENTIFIER, "identifier");
for (Member = TypePtr->Start; Member != NULL; Member = Member->NextSymbol) { for (Member = TypePtr->Start; Member != NULL; Member = Member->NextSymbol) {
printf("\tComparing struct entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier, printf("\tComparing composite entry %s with the wanted %s. Index %d.\r\n", Member->Name, CurrentIdentifier,
Member->SinkOffset); Member->SinkOffset);
if (!strcmp(Member->Name, CurrentIdentifier)) if (!strcmp(Member->Name, CurrentIdentifier))
break; break;
} }
if (Member == NULL) if (Member == NULL)
DieMessage("Invalid struct member", CurrentIdentifier); DieMessage("Invalid composite member", CurrentIdentifier);
RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset); RightNode = ConstructASTLeaf(TERM_INTLITERAL, RET_INT, NULL, Member->SinkOffset);

View File

@ -62,25 +62,26 @@ static int ReadDeclarationList(struct SymbolTableEntry* FunctionSymbol, int Stor
} }
/* /*
* Handles the declaration of a new struct. * Handles the declaration of a new composite type.
* For example, a struct is a composite of multiple different named positions:
* struct thisStct { int x, int y, int z }; * struct thisStct { int x, int y, int z };
* *
* Verifies that the current identifier is not used, * Verifies that the current identifier is not used,
* verifies that this is not a redefinition (excluding * verifies that this is not a redefinition (excluding
* the case where there is a declaration but no definition) * the case where there is a declaration but no definition)
* and then saves it into the Structs symbol table. * and then saves it into the appropriate symbol table.
* *
* @return the Symbol Table entry of this new struct. * @return the Symbol Table entry of this new composite.
*/ */
struct SymbolTableEntry* BeginStructDeclaration() { struct SymbolTableEntry* BeginCompositeDeclaration(int Type) {
struct SymbolTableEntry* Composite = NULL, * Member; struct SymbolTableEntry* Composite = NULL, * Member;
int Offset; int Offset = 0, Largest = 0;
Tokenise(); Tokenise();
if (CurrentToken.type == TY_IDENTIFIER) { if (CurrentToken.type == TY_IDENTIFIER) {
Composite = FindStruct(CurrentIdentifier); Composite = Type == DAT_STRUCT ? FindStruct(CurrentIdentifier) : FindUnion(CurrentIdentifier);
Tokenise(); Tokenise();
} }
@ -91,29 +92,34 @@ struct SymbolTableEntry* BeginStructDeclaration() {
} }
if (Composite) if (Composite)
DieMessage("Redefinition of struct", CurrentIdentifier); DieMessage("Redefinition of composite", CurrentIdentifier);
Composite = AddSymbol(CurrentIdentifier, DAT_STRUCT, 0, SC_STRUCT, 0, 0, NULL); Composite = AddSymbol(CurrentIdentifier, Type, 0, Type == DAT_STRUCT ? SC_STRUCT : SC_UNION, 0, 0, NULL);
Tokenise(); Tokenise();
printf("Reading a struct declaration..\n"); printf("Reading a composite declaration.. Type is %s\n", Type == DAT_STRUCT ? "struct" : "union");
ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAC); ReadDeclarationList(NULL, SC_MEMBER, LI_RBRAC);
VerifyToken(LI_RBRAC, "}"); VerifyToken(LI_RBRAC, "}");
Composite->Start = StructMembers; Composite->Start = CompositeMembers;
StructMembers = StructMembersEnd = NULL; CompositeMembers = CompositeMembersEnd = NULL;
Member = Composite->Start; Member = Composite->Start;
printf("\tSetting first entry in struct to %s\r\n", Member->Name); printf("\tSetting first entry in composite to %s\r\n", Member->Name);
Member->SinkOffset = 0; Member->SinkOffset = 0;
Offset = TypeSize(Member->Type, Member->CompositeType); Offset = TypeSize(Member->Type, Member->CompositeType);
for (Member = Member->NextSymbol; Member != NULL; Member = Member->NextSymbol) { for (Member = Member->NextSymbol; Member != NULL; Member = Member->NextSymbol) {
if (Type == DAT_STRUCT)
Member->SinkOffset = AsAlignMemory(Member->Type, Offset, 1); Member->SinkOffset = AsAlignMemory(Member->Type, Offset, 1);
else
Member->SinkOffset = 0;
Offset += TypeSize(Member->Type, Member->CompositeType); int CurrentSize = TypeSize(Member->Type, Member->CompositeType);
Offset += CurrentSize;
Largest = CurrentSize > Largest ? CurrentSize : Largest;
} }
Composite->Length = Offset; Composite->Length = Type == DAT_STRUCT ? Offset : Largest;
return Composite; return Composite;
} }

View File

@ -120,6 +120,16 @@ struct SymbolTableEntry* FindGlobal(char* Symbol) {
struct SymbolTableEntry* FindStruct(char* Symbol) { struct SymbolTableEntry* FindStruct(char* Symbol) {
return SearchList(Symbol, Structs); return SearchList(Symbol, Structs);
} }
/*
* An override for FindSymbol.
* Searches only the defined Unions.
* @param Symbol: The string name of the symbol to search for.
* @return a pointer to the node if found, else NULL
*
*/
struct SymbolTableEntry* FindUnion(char* Symbol) {
return SearchList(Symbol, Unions);
}
/* /*
* An override for FindSymbol. * An override for FindSymbol.
@ -129,7 +139,7 @@ struct SymbolTableEntry* FindStruct(char* Symbol) {
* *
*/ */
struct SymbolTableEntry* FindMember(char* Symbol) { struct SymbolTableEntry* FindMember(char* Symbol) {
return SearchList(Symbol, StructMembers); return SearchList(Symbol, CompositeMembers);
} }
/* /*
@ -177,7 +187,7 @@ void ClearTables() {
Globals = GlobalsEnd = NULL; Globals = GlobalsEnd = NULL;
Locals = LocalsEnd = NULL; Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL; Params = ParamsEnd = NULL;
StructMembers = StructMembersEnd = NULL; CompositeMembers = CompositeMembersEnd = NULL;
Structs = StructsEnd = NULL; Structs = StructsEnd = NULL;
} }
@ -218,8 +228,12 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
case SC_STRUCT: case SC_STRUCT:
AppendSymbol(&Structs, &StructsEnd, Node); AppendSymbol(&Structs, &StructsEnd, Node);
break; break;
case SC_UNION:
AppendSymbol(&Unions, &UnionsEnd, Node);
break;
case SC_MEMBER: case SC_MEMBER:
AppendSymbol(&StructMembers, &StructMembersEnd, Node); AppendSymbol(&CompositeMembers, &CompositeMembersEnd, Node);
break;
case SC_LOCAL: case SC_LOCAL:
AppendSymbol(&Locals, &LocalsEnd, Node); AppendSymbol(&Locals, &LocalsEnd, Node);
break; break;

View File

@ -64,7 +64,7 @@ int PrimitiveSize(int Type) {
*/ */
int TypeSize(int Type, struct SymbolTableEntry* Composite) { int TypeSize(int Type, struct SymbolTableEntry* Composite) {
if (Type == DAT_STRUCT) return Composite->Length; if (Type == DAT_STRUCT || Type == DAT_UNION) return Composite->Length;
return PrimitiveSize(Type); return PrimitiveSize(Type);
} }

21
tests/union.er Normal file
View File

@ -0,0 +1,21 @@
int :: printf(char* format);
union fruit {
char cherry,
int apple,
int orange,
long banana
};
union fruit basket;
int :: main() {
basket.apple = 55;
printf("1 %d b\n", basket.cherry);
printf("2 %d a\n", basket.orange);
basket.orange = 100;
printf("3 %d c\n", basket.banana);
printf("4 %d d\n", basket.apple);
return (0);
}