Refactor to allow inline initialization of arrays.
This commit is contained in:
parent
e42a2cfd8d
commit
0f77480d5b
|
@ -239,15 +239,16 @@ struct SymbolTableEntry {
|
|||
struct SymbolTableEntry* CompositeType; // A pointer to the start of a Symbol Table list that represents a certain Composite type
|
||||
int Structure; // An entry in StructureType - metadata on how to process the data
|
||||
int Storage; // The scope of this symbol - decides when it is discarded.
|
||||
union {
|
||||
int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable)
|
||||
int Length; // For an array - The length of the symbol in units of 1 element -- the size of an array, for example.
|
||||
int IntValue; // For an enum - The value of an Enum entry
|
||||
};
|
||||
int Length; // Size of an array, or the number of parameters in a function
|
||||
int Size; // Total size in bytes.
|
||||
|
||||
int* InitialValues;
|
||||
|
||||
int IntValue; // For an enum - The value of an Enum entry
|
||||
|
||||
union {
|
||||
int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable)
|
||||
int SinkOffset; // For a variable - How many times must we sink the rbp to get to this symbol in the stack?
|
||||
int Elements; // For a function - How many parameters?
|
||||
};
|
||||
|
||||
struct SymbolTableEntry* NextSymbol; // The next symbol in a list
|
||||
|
|
121
src/Statements.c
121
src/Statements.c
|
@ -61,6 +61,33 @@ struct ASTNode* ParseCompound() {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a literal of the given type.
|
||||
* @param Type integer or char*
|
||||
* @return the integer literal, or label value of the string.
|
||||
*/
|
||||
int ParseLiteral(int Type) {
|
||||
if ((Type == PointerTo(RET_CHAR)) && (CurrentFile->CurrentSymbol.type == LI_STR))
|
||||
return Assembler->vtable->AsNewString(CurrentIdentifier);
|
||||
|
||||
if (CurrentFile->CurrentSymbol.type == LI_INT) {
|
||||
switch (Type) {
|
||||
case RET_CHAR:
|
||||
if (CurrentFile->CurrentSymbol.value < 0 || CurrentFile->CurrentSymbol.value > 255)
|
||||
ErrorReport("Integer literal value too big for char\n");
|
||||
case RET_INT:
|
||||
case RET_LONG:
|
||||
break;
|
||||
|
||||
default: ErrorReport("Type Mismatch. Integer Literal vs Variable.\n");
|
||||
}
|
||||
} else {
|
||||
ErrorReport("Expecting an integer literal or char array.\n");
|
||||
}
|
||||
|
||||
return CurrentFile->CurrentSymbol.value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve a typename to a type struct.
|
||||
* Short circuit on the case where a definition is present, as definitions are typeless.
|
||||
|
@ -158,31 +185,94 @@ static int ParsePointerType(int Type) {
|
|||
*/
|
||||
static struct SymbolTableEntry* ParseArrayDeclaration(char* name, int Type, struct SymbolTableEntry* CompositeType, int Storage) {
|
||||
struct SymbolTableEntry* Symbol = NULL;
|
||||
int Elems = -1, MaxElems, *InitialList, i, j;
|
||||
|
||||
Tokenise();
|
||||
Safe();
|
||||
|
||||
if (CurrentFile->CurrentSymbol.type == LI_INT) {
|
||||
switch (Storage) {
|
||||
case SC_GLOBAL:
|
||||
Symbol = AddSymbol(name, PointerTo(Type), ST_ARR, Storage, CurrentFile->CurrentSymbol.value, 0, CompositeType);
|
||||
break;
|
||||
case SC_LOCAL:
|
||||
case SC_PARAM:
|
||||
case SC_MEMBER:
|
||||
default:
|
||||
ErrorReport("Local array definitions not permitted.\n");
|
||||
}
|
||||
if (CurrentFile->CurrentSymbol.value <= 0)
|
||||
ErrorReport("Array size in definition cannot be negative.\n");
|
||||
Elems = CurrentFile->CurrentSymbol.value;
|
||||
Tokenise();
|
||||
}
|
||||
|
||||
Tokenise();
|
||||
VerifyToken(LI_RBRAC, "]");
|
||||
Safe();
|
||||
|
||||
if (CurrentFile->CurrentSymbol.type == LI_EQUAL) {
|
||||
if (Storage != SC_GLOBAL)
|
||||
ErrorReport("Non-global array cannot be initialized.\n");
|
||||
Tokenise();
|
||||
Safe();
|
||||
|
||||
VerifyToken(LI_LBRAC, "{");
|
||||
|
||||
if (Elems != -1)
|
||||
MaxElems = Elems;
|
||||
else
|
||||
MaxElems = 10;
|
||||
InitialList = (int*)malloc(MaxElems * sizeof(int));
|
||||
|
||||
while (1) {
|
||||
if (Elems != -1 && i == MaxElems)
|
||||
ErrorReport("Too many items in initializer list\n");
|
||||
InitialList[i++] = ParseLiteral(Type);
|
||||
Tokenise();
|
||||
Safe();
|
||||
|
||||
if (Elems == -1 && i == MaxElems) {
|
||||
MaxElems += 10;
|
||||
InitialList = (int*)realloc(InitialList, MaxElems * sizeof(int));
|
||||
}
|
||||
|
||||
if (CurrentFile->CurrentSymbol.type == LI_RBRAC) {
|
||||
Tokenise();
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyToken(LI_COM, ",");
|
||||
Safe();
|
||||
}
|
||||
|
||||
for (j = i; j < Symbol->Length; j++)
|
||||
InitialList[j] = 0;
|
||||
if (i > Elems)
|
||||
Elems = i;
|
||||
Symbol->InitialValues = InitialList;
|
||||
}
|
||||
|
||||
Symbol->Length = Elems;
|
||||
Symbol->Size = Symbol->Length * TypeSize(Type, CompositeType);
|
||||
|
||||
if (Storage == SC_GLOBAL)
|
||||
Assembler->vtable->AsGlobalSymbol(Symbol);
|
||||
|
||||
return Symbol;
|
||||
}
|
||||
|
||||
// A short redirect to add a Scalar definition to the variable tables.
|
||||
static struct SymbolTableEntry* ParseScalarDeclaration(char* name, int Type, struct SymbolTableEntry* CompositeType, int Storage) {
|
||||
return AddSymbol(name, Type, ST_VAR, Storage, 1, 0, CompositeType);
|
||||
struct SymbolTableEntry* sym = AddSymbol(name, Type, ST_VAR, Storage, 1, 0, CompositeType);
|
||||
|
||||
// Being assigned.
|
||||
if (CurrentFile->CurrentSymbol.type == LI_EQUAL) {
|
||||
if (Storage != SC_GLOBAL && Storage != SC_LOCAL)
|
||||
ErrorReport("Non-static, non-local variable cannot be initialized.\n");
|
||||
Tokenise();
|
||||
Safe();
|
||||
|
||||
if (Storage == SC_GLOBAL) {
|
||||
sym->InitialValues = (int*) malloc(sizeof(int));
|
||||
sym->InitialValues[0] = ParseLiteral(Type);
|
||||
Tokenise();
|
||||
}
|
||||
}
|
||||
|
||||
if (Storage == SC_GLOBAL)
|
||||
Assembler->vtable->AsGlobalSymbol(sym);
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -323,7 +413,7 @@ static struct SymbolTableEntry* ParseFunctionDeclaration(char* name, int Type, s
|
|||
TypeNames(Type), BreakLabel);
|
||||
|
||||
if (NewFunction) {
|
||||
NewFunction->Elements = ParamCount;
|
||||
NewFunction->Length = ParamCount;
|
||||
NewFunction->Start = Params;
|
||||
NewFunction->Type = RET_LONG;
|
||||
OldFunction = NewFunction;
|
||||
|
@ -584,6 +674,7 @@ struct SymbolTableEntry* BeginCompositeDeclaration(int Type) {
|
|||
}
|
||||
|
||||
Composite->Length = Type == DAT_STRUCT ? Offset : Largest;
|
||||
Composite->Size = Offset;
|
||||
return Composite;
|
||||
}
|
||||
|
||||
|
@ -904,8 +995,8 @@ struct ASTNode* SwitchStatement() {
|
|||
VerifyToken(LI_LBRAC, "{");
|
||||
|
||||
// Verify the switch expression (must be integer-compatible)
|
||||
if (!TypeIsInt(!left->ExprType))
|
||||
Die("Switch expression is not of integer type");
|
||||
if (!TypeIsInt(left->ExprType))
|
||||
ErrorReport("Switch expression is not of integer type, instead %s.\n", TypeNames(left->ExprType));
|
||||
|
||||
Safe();
|
||||
|
||||
|
|
|
@ -251,6 +251,9 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
|
|||
Node->SinkOffset = SinkOffset;
|
||||
Node->CompositeType = CompositeType;
|
||||
|
||||
if (TypeIsPtr(Type) || TypeIsInt(Type))
|
||||
Node->Size = Length * TypeSize(Type, CompositeType);
|
||||
|
||||
printf("Adding a %s symbol of name %s, type %s to the tables.\n", ScopeNames[Node->Storage], Node->Name,
|
||||
TypeNames(Node->Type));
|
||||
switch (Storage) {
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
*/
|
||||
|
||||
int TypeIsInt(int Type) {
|
||||
return ((Type & 0xf) == 0);
|
||||
printf("\tComparing type %d.\n", Type);
|
||||
return ( ((Type & 0xf) == 0) && (Type >= RET_CHAR && Type <= RET_LONG));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -712,34 +712,51 @@ static int AsStrDeref(int Register1, int Register2, int Type) {
|
|||
return Register1;
|
||||
}
|
||||
|
||||
static void AsDataSegment() {
|
||||
fprintf(stdout, ".data:\n");
|
||||
}
|
||||
|
||||
// Assemble a global symbol (variable, struct, enum, function, string)
|
||||
static void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
|
||||
int size, type, init, i;
|
||||
|
||||
if (Entry == NULL) return;
|
||||
if (Entry->Structure == ST_FUNC) return;
|
||||
|
||||
if (Entry->Structure = ST_ARR) {
|
||||
type = ValueAt(Entry->Type);
|
||||
size = TypeSize(type, Entry->CompositeType);
|
||||
} else {
|
||||
size = Entry->Size;
|
||||
type = Entry->Type;
|
||||
}
|
||||
|
||||
int Size = TypeSize(Entry->Type, Entry->CompositeType);
|
||||
|
||||
fprintf(OutputFile, "\t.data\n"
|
||||
"\t.globl\t%s\n",
|
||||
Entry->Name);
|
||||
|
||||
AsDataSegment();
|
||||
fprintf(OutputFile,"\t.globl\t%s\n", Entry->Name);
|
||||
fprintf(OutputFile, "%s:\n", Entry->Name);
|
||||
|
||||
switch (Size) {
|
||||
case 1:
|
||||
fprintf(OutputFile, "\t.byte\t0\r\n");
|
||||
break;
|
||||
case 4:
|
||||
fprintf(OutputFile, "\t.long\t0\r\n");
|
||||
break;
|
||||
case 8:
|
||||
fprintf(OutputFile, "\t.quad\t0\r\n");
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < Size; i++)
|
||||
fprintf(OutputFile, "\t.byte\t0\n");
|
||||
for (i = 0; i < Entry->Length; i++) {
|
||||
init = 0;
|
||||
if (Entry->InitialValues)
|
||||
init = Entry->InitialValues[i];
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
fprintf(OutputFile, "\t.byte\t0\r\n");
|
||||
break;
|
||||
case 4:
|
||||
fprintf(OutputFile, "\t.long\t0\r\n");
|
||||
break;
|
||||
case 8:
|
||||
if (Entry->InitialValues && type == PointerTo(RET_CHAR))
|
||||
fprintf(OutputFile, "\t.quad\tL%d\r\n", init);
|
||||
else
|
||||
fprintf(OutputFile, "\t.quad\t%d\r\n", init);
|
||||
break;
|
||||
default:
|
||||
for (i = 0; i < size; i++)
|
||||
fprintf(OutputFile, "\t.byte\t0\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user