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* 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -87,6 +87,7 @@ char* ScopeNames[] = {
|
|||
"INVALID",
|
||||
"GLOBAL",
|
||||
"STRUCT",
|
||||
"UNION",
|
||||
"ENUM",
|
||||
"MEMBER",
|
||||
"PARAMETER",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
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