Handled struct members which are pointers to data with the type of the containing struct. ie struct foo { foo* Next; }

This commit is contained in:
Peter Slattery 2020-01-19 00:14:14 -08:00
parent 9d0e4149d9
commit 9a228d22ba
2 changed files with 84 additions and 58 deletions

View File

@ -1,3 +1,15 @@
//
// Usage
//
// GSMetaTag(<tag name>) to give commands to the meta layer
//
// Tag Values
//
// breakpoint
// will cause the meta layer to break in the debugger when it reaches
// that point in processing the file
// TODO: specify which stage you want it to break at
#include <windows.h>
#include <stdio.h>
@ -354,7 +366,15 @@ ParseMetaTag(token_iter* Iter, gs_bucket<token*>* TagList)
if (Iter->TokenAt->Type == Token_Identifier)
{
TagList->PushElementOnBucket(Iter->TokenAt);
if (StringsEqual(Iter->TokenAt->Text, MakeStringLiteral("breakpoint")))
{
// NOTE(Peter): This is not a temporary breakpoint. It is
// used to be able to break the meta program at specific points
// throughout execution
__debugbreak();
}
NextToken(Iter);
if (TokenAtEquals(Iter, ")") &&
TokenAtEquals(Iter, ";"))
{
@ -790,7 +810,7 @@ ParseStruct(token_iter* Iter, s32* StructTypeIndexOut, gs_bucket<token*>* TagLis
if (TokenAtEquals(Iter, ";"))
{
Result = true;
*StructTypeIndexOut = TypeTable->Types.PushElementOnBucket(StructDecl);
*StructTypeIndexOut = PushTypeDefOnTypeTable(StructDecl, TypeTable);
}
}
}
@ -872,7 +892,7 @@ ParseFunctionDeclaration (token_iter* Iter, token* Identifier, gs_bucket<token*>
if (TokenAtEquals(Iter, ";"))
{
Result = true;
TypeTable->Types.PushElementOnBucket(FunctionPtr);
PushTypeDefOnTypeTable(FunctionPtr, TypeTable);
}
}
}
@ -934,17 +954,7 @@ ParseTypedef(token_iter* Iter, gs_bucket<token*>* TagList, type_table* TypeTable
NextToken(Iter);
Result = true;
s32 ExistingUndeclaredTypeIndex = GetIndexOfType(NewType.Identifier, *TypeTable);
if (ExistingUndeclaredTypeIndex < 0)
{
TypeTable->Types.PushElementOnBucket(NewType);
}
else
{
type_definition* ExistingTypeDef = TypeTable->Types.GetElementAtIndex(ExistingUndeclaredTypeIndex);
*ExistingTypeDef = NewType;
}
PushTypeDefOnTypeTable(NewType, TypeTable);
}
}
else
@ -1190,11 +1200,11 @@ int main(int ArgCount, char** ArgV)
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i);
if (TypeDef->Type == TypeDef_Struct)
{
FixUpStructSize(TypeDef, TypeTable);
FixUpStructSize(i, TypeTable);
}
else if (TypeDef->Type == TypeDef_Union)
{
FixUpUnionSize(TypeDef, TypeTable);
FixUpUnionSize(i, TypeTable);
}
}

View File

@ -78,6 +78,19 @@ struct type_table
gs_bucket<type_definition> Types;
};
internal void
MetaTagBreakpoint(gs_bucket<meta_tag> Tags)
{
for (u32 i = 0; i < Tags.Used; i++)
{
meta_tag* Tag = Tags.GetElementAtIndex(i);
if (StringsEqual(Tag->Identifier, MakeStringLiteral("breakpoint")))
{
__debugbreak();
}
}
}
internal void
CopyMetaTagsAndClear(gs_bucket<token*>* Source, gs_bucket<meta_tag>* Dest)
{
@ -91,35 +104,6 @@ CopyMetaTagsAndClear(gs_bucket<token*>* Source, gs_bucket<meta_tag>* Dest)
Source->Used = 0;
}
internal type_definition*
PushStructOnTypeTable(string Identifier, type_definition_type DeclType, gs_bucket<token*>* TagList, type_table* TypeTable)
{
Assert(DeclType == TypeDef_Struct || DeclType == TypeDef_Union);
type_definition* Result = TypeTable->Types.TakeElement();
*Result = {0};
Result->Type = DeclType;
Result->Identifier = Identifier;
CopyMetaTagsAndClear(TagList, &Result->MetaTags);
return Result;
}
internal s32
PushTypeDefOnTypeTable(type_definition TypeDef, type_table* TypeTable)
{
s32 Index = -1;
if (TypeDef.Type != TypeDef_BasicType)
{
printf("Invalid TypeDef: %.*s\n", StringExpand(TypeDef.Identifier));
}
else
{
Index = TypeTable->Types.PushElementOnBucket(TypeDef);
}
return Index;
}
internal s32
PushUndeclaredType (string Identifier, type_table* TypeTable)
{
@ -146,6 +130,26 @@ GetIndexOfType (string Identifier, type_table TypeTable)
return Result;
}
internal s32
PushTypeDefOnTypeTable(type_definition TypeDef, type_table* TypeTable)
{
s32 Index = -1;
s32 ExistingUndeclaredTypeIndex = GetIndexOfType(TypeDef.Identifier, *TypeTable);
if (ExistingUndeclaredTypeIndex < 0)
{
Index = TypeTable->Types.PushElementOnBucket(TypeDef);
}
else
{
Index = ExistingUndeclaredTypeIndex;
type_definition* ExistingTypeDef = TypeTable->Types.GetElementAtIndex(ExistingUndeclaredTypeIndex);
*ExistingTypeDef = TypeDef;
}
return Index;
}
internal s32
GetSizeOfType (s32 TypeIndex, type_table TypeTable)
{
@ -241,8 +245,8 @@ FindIndexOfMatchingType (type_definition Match, type_table TypeTable)
return Result;
}
internal void FixUpStructSize (type_definition* Struct, type_table TypeTable);
internal void FixUpUnionSize (type_definition* Union, type_table TypeTable);
internal void FixUpStructSize (s32 StructIndex, type_table TypeTable);
internal void FixUpUnionSize (s32 UnionIndex, type_table TypeTable);
internal void
FixupMemberType (variable_decl* Member, type_table TypeTable)
@ -275,10 +279,13 @@ CalculateStructMemberSize (variable_decl Member, type_definition MemberType)
}
internal void
FixUpStructSize (type_definition* Struct, type_table TypeTable)
FixUpStructSize (s32 StructIndex, type_table TypeTable)
{
type_definition* Struct = TypeTable.Types.GetElementAtIndex(StructIndex);
Assert(Struct->Type == TypeDef_Struct);
MetaTagBreakpoint(Struct->MetaTags);
s32 SizeAcc = 0;
for (u32 j = 0; j < Struct->Struct.MemberDecls.Used; j++)
{
@ -288,15 +295,23 @@ FixUpStructSize (type_definition* Struct, type_table TypeTable)
if (Member->TypeIndex >= 0)
{
type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex);
if (MemberTypeDef->Size == 0)
// NOTE(Peter): This signals a nested pointer to an address of the
// same type as the one we are parsing now. In that case, the size
// also hasn't been determined yet, but we know the size of the member
// is just a pointer (32 or 64 bits).
// For example, this would go into an infinite recursion without the case
// of StructIndex != Member->TypeIndex:
// struct foo { foo* Next; }
if (MemberTypeDef->Size == 0 && StructIndex != Member->TypeIndex)
{
if (MemberTypeDef->Type == TypeDef_Struct)
{
FixUpStructSize(MemberTypeDef, TypeTable);
FixUpStructSize(Member->TypeIndex, TypeTable);
}
else if(MemberTypeDef->Type == TypeDef_Union)
else if (MemberTypeDef->Type == TypeDef_Union)
{
FixUpUnionSize(MemberTypeDef, TypeTable);
FixUpUnionSize(Member->TypeIndex, TypeTable);
}
else
{
@ -305,7 +320,7 @@ FixUpStructSize (type_definition* Struct, type_table TypeTable)
#if 0
InvalidCodePath;
#else
printf("Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
printf("Struct Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
#endif
}
}
@ -327,14 +342,15 @@ FixUpStructSize (type_definition* Struct, type_table TypeTable)
#else
if (Struct->Size == 0)
{
printf("Error: Struct Size = 0. %.*s\n", StringExpand(Struct->Identifier));
printf("Struct Error: Struct Size = 0. %.*s\n", StringExpand(Struct->Identifier));
}
#endif
}
internal void
FixUpUnionSize (type_definition* Union, type_table TypeTable)
FixUpUnionSize (s32 UnionIndex, type_table TypeTable)
{
type_definition* Union = TypeTable.Types.GetElementAtIndex(UnionIndex);
Assert(Union->Type == TypeDef_Union);
s32 BiggestMemberSize = 0;
@ -350,11 +366,11 @@ FixUpUnionSize (type_definition* Union, type_table TypeTable)
{
if (MemberTypeDef->Type == TypeDef_Struct)
{
FixUpStructSize(MemberTypeDef, TypeTable);
FixUpStructSize(Member->TypeIndex, TypeTable);
}
else if(MemberTypeDef->Type == TypeDef_Union)
{
FixUpUnionSize(MemberTypeDef, TypeTable);
FixUpUnionSize(Member->TypeIndex, TypeTable);
}
else
{
@ -363,7 +379,7 @@ FixUpUnionSize (type_definition* Union, type_table TypeTable)
#if 0
InvalidCodePath;
#else
printf("Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
printf("Union Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
#endif
}
}
@ -385,7 +401,7 @@ FixUpUnionSize (type_definition* Union, type_table TypeTable)
#else
if (Union->Size == 0)
{
printf("Error: Struct Size = 0. %.*s\n", StringExpand(Union->Identifier));
printf("Union Error: Struct Size = 0. %.*s\n", StringExpand(Union->Identifier));
}
#endif
}