Implement unions and largest-element allocation
This commit is contained in:
parent
537246daae
commit
3717b310be
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -87,6 +87,7 @@ char* ScopeNames[] = {
|
||||||
"INVALID",
|
"INVALID",
|
||||||
"GLOBAL",
|
"GLOBAL",
|
||||||
"STRUCT",
|
"STRUCT",
|
||||||
|
"UNION",
|
||||||
"ENUM",
|
"ENUM",
|
||||||
"MEMBER",
|
"MEMBER",
|
||||||
"PARAMETER",
|
"PARAMETER",
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
Member->SinkOffset = AsAlignMemory(Member->Type, Offset, 1);
|
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;
|
return Composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
21
tests/union.er
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user