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* Params, * ParamsEnd;
extern_ struct SymbolTableEntry* Structs, * StructsEnd;
extern_ struct SymbolTableEntry* StructMembers, * StructMembersEnd;
extern_ struct SymbolTableEntry* CompositeMembers, * CompositeMembersEnd;
extern_ struct SymbolTableEntry* Unions, * UnionsEnd;
extern_ struct SymbolTableEntry* Enums, * EnumsEnd;

View File

@ -96,7 +96,8 @@ enum TokenTypes {
KW_WHILE,
KW_FOR,
KW_RETURN,
KW_STRUCT
KW_STRUCT,
KW_UNION
};
/*
@ -219,6 +220,7 @@ struct SymbolTableEntry {
enum StorageScope {
SC_GLOBAL = 1, // Global Scope
SC_STRUCT, // Struct Definitions
SC_UNION, // Union Definitions
SC_ENUM, // Enum Definitions
SC_MEMBER, // The members of Structs or Enums
//SC_CLASS, // Class-local definitions
@ -348,7 +350,7 @@ struct ASTNode* ParseFunction(int Type);
struct ASTNode* ParseCompound();
struct SymbolTableEntry* BeginStructDeclaration();
struct SymbolTableEntry* BeginCompositeDeclaration(int Type);
struct ASTNode* GetExpressionList();
@ -387,6 +389,8 @@ struct SymbolTableEntry* FindGlobal(char* Symbol);
struct SymbolTableEntry* FindStruct(char* Symbol);
struct SymbolTableEntry* FindUnion(char* Symbol);
struct SymbolTableEntry* FindMember(char* Symbol);
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]);
switch (DestSize) {
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;
case 2:
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;
break;
case 'u':
if(!strcmp(Str, "union"))
return KW_UNION;
break;
case 'v':
if (!strcmp(Str, "void"))
return TY_VOID;

View File

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

View File

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

View File

@ -94,7 +94,11 @@ int ParseOptionalPointer(struct SymbolTableEntry** Composite) {
break;
case KW_STRUCT:
Type = DAT_STRUCT;
*Composite = BeginStructDeclaration();
*Composite = BeginCompositeDeclaration(Type);
break;
case KW_UNION:
Type = DAT_UNION;
*Composite = BeginCompositeDeclaration(Type);
break;
default:
DieDecimal("Illegal type for pointerisation", CurrentToken.type);
@ -175,13 +179,13 @@ struct ASTNode* AccessMember(bool Deref) {
if ((CompositeVar = FindSymbol(CurrentIdentifier)) == NULL)
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);
if (!Deref && CompositeVar->Type != DAT_STRUCT)
if (!Deref && (CompositeVar->Type != DAT_STRUCT && CompositeVar->Type != DAT_UNION))
DieMessage("Undeclared struct", CurrentIdentifier);
if (Deref)
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(DAT_STRUCT), CompositeVar, 0);
LeftNode = ConstructASTLeaf(REF_IDENT, PointerTo(CompositeVar->Type), CompositeVar, 0);
else
LeftNode = ConstructASTLeaf(OP_ADDRESS, CompositeVar->Type, CompositeVar, 0);
@ -193,14 +197,14 @@ struct ASTNode* AccessMember(bool Deref) {
VerifyToken(TY_IDENTIFIER, "identifier");
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);
if (!strcmp(Member->Name, CurrentIdentifier))
break;
}
if (Member == NULL)
DieMessage("Invalid struct member", CurrentIdentifier);
DieMessage("Invalid composite member", CurrentIdentifier);
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 };
*
* Verifies that the current identifier is not used,
* verifies that this is not a redefinition (excluding
* 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;
int Offset;
int Offset = 0, Largest = 0;
Tokenise();
if (CurrentToken.type == TY_IDENTIFIER) {
Composite = FindStruct(CurrentIdentifier);
Composite = Type == DAT_STRUCT ? FindStruct(CurrentIdentifier) : FindUnion(CurrentIdentifier);
Tokenise();
}
@ -91,29 +92,34 @@ struct SymbolTableEntry* BeginStructDeclaration() {
}
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();
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);
VerifyToken(LI_RBRAC, "}");
Composite->Start = StructMembers;
StructMembers = StructMembersEnd = NULL;
Composite->Start = CompositeMembers;
CompositeMembers = CompositeMembersEnd = NULL;
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;
Offset = TypeSize(Member->Type, Member->CompositeType);
for (Member = Member->NextSymbol; Member != NULL; Member = Member->NextSymbol) {
if (Type == DAT_STRUCT)
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;
}

View File

@ -120,6 +120,16 @@ struct SymbolTableEntry* FindGlobal(char* Symbol) {
struct SymbolTableEntry* FindStruct(char* Symbol) {
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.
@ -129,7 +139,7 @@ struct SymbolTableEntry* FindStruct(char* Symbol) {
*
*/
struct SymbolTableEntry* FindMember(char* Symbol) {
return SearchList(Symbol, StructMembers);
return SearchList(Symbol, CompositeMembers);
}
/*
@ -177,7 +187,7 @@ void ClearTables() {
Globals = GlobalsEnd = NULL;
Locals = LocalsEnd = NULL;
Params = ParamsEnd = NULL;
StructMembers = StructMembersEnd = NULL;
CompositeMembers = CompositeMembersEnd = NULL;
Structs = StructsEnd = NULL;
}
@ -218,8 +228,12 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
case SC_STRUCT:
AppendSymbol(&Structs, &StructsEnd, Node);
break;
case SC_UNION:
AppendSymbol(&Unions, &UnionsEnd, Node);
break;
case SC_MEMBER:
AppendSymbol(&StructMembers, &StructMembersEnd, Node);
AppendSymbol(&CompositeMembers, &CompositeMembersEnd, Node);
break;
case SC_LOCAL:
AppendSymbol(&Locals, &LocalsEnd, Node);
break;

View File

@ -64,7 +64,7 @@ int PrimitiveSize(int Type) {
*/
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);
}

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);
}