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
|
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 Structure; // An entry in StructureType - metadata on how to process the data
|
||||||
int Storage; // The scope of this symbol - decides when it is discarded.
|
int Storage; // The scope of this symbol - decides when it is discarded.
|
||||||
union {
|
int Length; // Size of an array, or the number of parameters in a function
|
||||||
int EndLabel; // For a function - The number of the label to jump to, in order to exit this function (if applicable)
|
int Size; // Total size in bytes.
|
||||||
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* InitialValues;
|
||||||
};
|
|
||||||
|
int IntValue; // For an enum - The value of an Enum entry
|
||||||
|
|
||||||
union {
|
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 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
|
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.
|
* Resolve a typename to a type struct.
|
||||||
* Short circuit on the case where a definition is present, as definitions are typeless.
|
* 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) {
|
static struct SymbolTableEntry* ParseArrayDeclaration(char* name, int Type, struct SymbolTableEntry* CompositeType, int Storage) {
|
||||||
struct SymbolTableEntry* Symbol = NULL;
|
struct SymbolTableEntry* Symbol = NULL;
|
||||||
|
int Elems = -1, MaxElems, *InitialList, i, j;
|
||||||
|
|
||||||
Tokenise();
|
Tokenise();
|
||||||
Safe();
|
Safe();
|
||||||
|
|
||||||
if (CurrentFile->CurrentSymbol.type == LI_INT) {
|
if (CurrentFile->CurrentSymbol.type == LI_INT) {
|
||||||
switch (Storage) {
|
if (CurrentFile->CurrentSymbol.value <= 0)
|
||||||
case SC_GLOBAL:
|
ErrorReport("Array size in definition cannot be negative.\n");
|
||||||
Symbol = AddSymbol(name, PointerTo(Type), ST_ARR, Storage, CurrentFile->CurrentSymbol.value, 0, CompositeType);
|
Elems = CurrentFile->CurrentSymbol.value;
|
||||||
break;
|
Tokenise();
|
||||||
case SC_LOCAL:
|
|
||||||
case SC_PARAM:
|
|
||||||
case SC_MEMBER:
|
|
||||||
default:
|
|
||||||
ErrorReport("Local array definitions not permitted.\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokenise();
|
|
||||||
VerifyToken(LI_RBRAC, "]");
|
VerifyToken(LI_RBRAC, "]");
|
||||||
Safe();
|
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;
|
return Symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A short redirect to add a Scalar definition to the variable tables.
|
// 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) {
|
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);
|
TypeNames(Type), BreakLabel);
|
||||||
|
|
||||||
if (NewFunction) {
|
if (NewFunction) {
|
||||||
NewFunction->Elements = ParamCount;
|
NewFunction->Length = ParamCount;
|
||||||
NewFunction->Start = Params;
|
NewFunction->Start = Params;
|
||||||
NewFunction->Type = RET_LONG;
|
NewFunction->Type = RET_LONG;
|
||||||
OldFunction = NewFunction;
|
OldFunction = NewFunction;
|
||||||
|
@ -584,6 +674,7 @@ struct SymbolTableEntry* BeginCompositeDeclaration(int Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Composite->Length = Type == DAT_STRUCT ? Offset : Largest;
|
Composite->Length = Type == DAT_STRUCT ? Offset : Largest;
|
||||||
|
Composite->Size = Offset;
|
||||||
return Composite;
|
return Composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,8 +995,8 @@ struct ASTNode* SwitchStatement() {
|
||||||
VerifyToken(LI_LBRAC, "{");
|
VerifyToken(LI_LBRAC, "{");
|
||||||
|
|
||||||
// Verify the switch expression (must be integer-compatible)
|
// Verify the switch expression (must be integer-compatible)
|
||||||
if (!TypeIsInt(!left->ExprType))
|
if (!TypeIsInt(left->ExprType))
|
||||||
Die("Switch expression is not of integer type");
|
ErrorReport("Switch expression is not of integer type, instead %s.\n", TypeNames(left->ExprType));
|
||||||
|
|
||||||
Safe();
|
Safe();
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,9 @@ struct SymbolTableEntry* AddSymbol(char* Name, int Type, int Structure, int Stor
|
||||||
Node->SinkOffset = SinkOffset;
|
Node->SinkOffset = SinkOffset;
|
||||||
Node->CompositeType = CompositeType;
|
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,
|
printf("Adding a %s symbol of name %s, type %s to the tables.\n", ScopeNames[Node->Storage], Node->Name,
|
||||||
TypeNames(Node->Type));
|
TypeNames(Node->Type));
|
||||||
switch (Storage) {
|
switch (Storage) {
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int TypeIsInt(int Type) {
|
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;
|
return Register1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AsDataSegment() {
|
||||||
|
fprintf(stdout, ".data:\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Assemble a global symbol (variable, struct, enum, function, string)
|
// Assemble a global symbol (variable, struct, enum, function, string)
|
||||||
static void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
|
static void AsGlobalSymbol(struct SymbolTableEntry* Entry) {
|
||||||
|
int size, type, init, i;
|
||||||
|
|
||||||
if (Entry == NULL) return;
|
if (Entry == NULL) return;
|
||||||
if (Entry->Structure == ST_FUNC) 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);
|
AsDataSegment();
|
||||||
|
fprintf(OutputFile,"\t.globl\t%s\n", Entry->Name);
|
||||||
fprintf(OutputFile, "\t.data\n"
|
|
||||||
"\t.globl\t%s\n",
|
|
||||||
Entry->Name);
|
|
||||||
|
|
||||||
fprintf(OutputFile, "%s:\n", Entry->Name);
|
fprintf(OutputFile, "%s:\n", Entry->Name);
|
||||||
|
|
||||||
switch (Size) {
|
for (i = 0; i < Entry->Length; i++) {
|
||||||
case 1:
|
init = 0;
|
||||||
fprintf(OutputFile, "\t.byte\t0\r\n");
|
if (Entry->InitialValues)
|
||||||
break;
|
init = Entry->InitialValues[i];
|
||||||
case 4:
|
|
||||||
fprintf(OutputFile, "\t.long\t0\r\n");
|
switch (size) {
|
||||||
break;
|
case 1:
|
||||||
case 8:
|
fprintf(OutputFile, "\t.byte\t0\r\n");
|
||||||
fprintf(OutputFile, "\t.quad\t0\r\n");
|
break;
|
||||||
break;
|
case 4:
|
||||||
default:
|
fprintf(OutputFile, "\t.long\t0\r\n");
|
||||||
for (int i = 0; i < Size; i++)
|
break;
|
||||||
fprintf(OutputFile, "\t.byte\t0\n");
|
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