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 <windows.h>
#include <stdio.h> #include <stdio.h>
@ -354,7 +366,15 @@ ParseMetaTag(token_iter* Iter, gs_bucket<token*>* TagList)
if (Iter->TokenAt->Type == Token_Identifier) if (Iter->TokenAt->Type == Token_Identifier)
{ {
TagList->PushElementOnBucket(Iter->TokenAt); 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); NextToken(Iter);
if (TokenAtEquals(Iter, ")") && if (TokenAtEquals(Iter, ")") &&
TokenAtEquals(Iter, ";")) TokenAtEquals(Iter, ";"))
{ {
@ -790,7 +810,7 @@ ParseStruct(token_iter* Iter, s32* StructTypeIndexOut, gs_bucket<token*>* TagLis
if (TokenAtEquals(Iter, ";")) if (TokenAtEquals(Iter, ";"))
{ {
Result = true; 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, ";")) if (TokenAtEquals(Iter, ";"))
{ {
Result = true; 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); NextToken(Iter);
Result = true; Result = true;
PushTypeDefOnTypeTable(NewType, TypeTable);
s32 ExistingUndeclaredTypeIndex = GetIndexOfType(NewType.Identifier, *TypeTable);
if (ExistingUndeclaredTypeIndex < 0)
{
TypeTable->Types.PushElementOnBucket(NewType);
}
else
{
type_definition* ExistingTypeDef = TypeTable->Types.GetElementAtIndex(ExistingUndeclaredTypeIndex);
*ExistingTypeDef = NewType;
}
} }
} }
else else
@ -1190,11 +1200,11 @@ int main(int ArgCount, char** ArgV)
type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i); type_definition* TypeDef = TypeTable.Types.GetElementAtIndex(i);
if (TypeDef->Type == TypeDef_Struct) if (TypeDef->Type == TypeDef_Struct)
{ {
FixUpStructSize(TypeDef, TypeTable); FixUpStructSize(i, TypeTable);
} }
else if (TypeDef->Type == TypeDef_Union) 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; 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 internal void
CopyMetaTagsAndClear(gs_bucket<token*>* Source, gs_bucket<meta_tag>* Dest) 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; 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 internal s32
PushUndeclaredType (string Identifier, type_table* TypeTable) PushUndeclaredType (string Identifier, type_table* TypeTable)
{ {
@ -146,6 +130,26 @@ GetIndexOfType (string Identifier, type_table TypeTable)
return Result; 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 internal s32
GetSizeOfType (s32 TypeIndex, type_table TypeTable) GetSizeOfType (s32 TypeIndex, type_table TypeTable)
{ {
@ -241,8 +245,8 @@ FindIndexOfMatchingType (type_definition Match, type_table TypeTable)
return Result; return Result;
} }
internal void FixUpStructSize (type_definition* Struct, type_table TypeTable); internal void FixUpStructSize (s32 StructIndex, type_table TypeTable);
internal void FixUpUnionSize (type_definition* Union, type_table TypeTable); internal void FixUpUnionSize (s32 UnionIndex, type_table TypeTable);
internal void internal void
FixupMemberType (variable_decl* Member, type_table TypeTable) FixupMemberType (variable_decl* Member, type_table TypeTable)
@ -275,10 +279,13 @@ CalculateStructMemberSize (variable_decl Member, type_definition MemberType)
} }
internal void 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); Assert(Struct->Type == TypeDef_Struct);
MetaTagBreakpoint(Struct->MetaTags);
s32 SizeAcc = 0; s32 SizeAcc = 0;
for (u32 j = 0; j < Struct->Struct.MemberDecls.Used; j++) 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) if (Member->TypeIndex >= 0)
{ {
type_definition* MemberTypeDef = TypeTable.Types.GetElementAtIndex(Member->TypeIndex); 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) 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 else
{ {
@ -305,7 +320,7 @@ FixUpStructSize (type_definition* Struct, type_table TypeTable)
#if 0 #if 0
InvalidCodePath; InvalidCodePath;
#else #else
printf("Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier)); printf("Struct Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
#endif #endif
} }
} }
@ -327,14 +342,15 @@ FixUpStructSize (type_definition* Struct, type_table TypeTable)
#else #else
if (Struct->Size == 0) 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 #endif
} }
internal void 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); Assert(Union->Type == TypeDef_Union);
s32 BiggestMemberSize = 0; s32 BiggestMemberSize = 0;
@ -350,11 +366,11 @@ FixUpUnionSize (type_definition* Union, type_table TypeTable)
{ {
if (MemberTypeDef->Type == TypeDef_Struct) 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 else
{ {
@ -363,7 +379,7 @@ FixUpUnionSize (type_definition* Union, type_table TypeTable)
#if 0 #if 0
InvalidCodePath; InvalidCodePath;
#else #else
printf("Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier)); printf("Union Error: TypeDef Size = 0. %.*s\n", StringExpand(MemberTypeDef->Identifier));
#endif #endif
} }
} }
@ -385,7 +401,7 @@ FixUpUnionSize (type_definition* Union, type_table TypeTable)
#else #else
if (Union->Size == 0) 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 #endif
} }