Fix break & continue implementation

This commit is contained in:
Curle 2022-03-06 01:15:07 +00:00
parent 0454c38a7e
commit 334b02cd76
8 changed files with 44 additions and 31 deletions

View File

@ -14,7 +14,6 @@
#endif #endif
#define TEXTLEN 512 #define TEXTLEN 512
#define SYMBOLS 1024
// All currently open source files. // All currently open source files.
extern_ struct FileData** Files; extern_ struct FileData** Files;
@ -60,5 +59,3 @@ extern_ int Overread;
extern_ char CurrentIdentifier[TEXTLEN + 1]; extern_ char CurrentIdentifier[TEXTLEN + 1];
extern_ int CurrentGlobal;
extern_ int CurrentLocal;

View File

@ -352,7 +352,7 @@ void Compile(struct FileData* InputFile);
void Assemble(struct FileData* InputFile); void Assemble(struct FileData* InputFile);
void Link(char* Output, struct FileData* Objects[]); void Link(char* Output, struct FileData* Objects[], int ObjectsLength);
void DisplayUsage(char* ProgName); void DisplayUsage(char* ProgName);

View File

@ -79,9 +79,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
return AsWhile(Node); return AsWhile(Node);
case OP_COMP: case OP_COMP:
AssembleTree(Node->Left, -1, -1, -1, Node->Operation); AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
DeallocateAllRegisters(); DeallocateAllRegisters();
AssembleTree(Node->Right, -1, -1, -1, Node->Operation); AssembleTree(Node->Right, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
DeallocateAllRegisters(); DeallocateAllRegisters();
return -1; return -1;
@ -90,17 +90,17 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
case OP_FUNC: case OP_FUNC:
AsFunctionPreamble(Node->Symbol); AsFunctionPreamble(Node->Symbol);
AssembleTree(Node->Left, -1, -1, -1, Node->Operation); AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
AsFunctionEpilogue(Node->Symbol); AsFunctionEpilogue(Node->Symbol);
return -1; return -1;
} }
if (Node->Left) if (Node->Left)
LeftVal = AssembleTree(Node->Left, -1, -1, -1, Node->Operation); LeftVal = AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
if (Node->Right) if (Node->Right)
RightVal = AssembleTree(Node->Right, LeftVal, -1, -1, Node->Operation); RightVal = AssembleTree(Node->Right, LeftVal, LoopBeginLabel, LoopEndLabel, Node->Operation);
switch (Node->Operation) { switch (Node->Operation) {
case OP_ADD: case OP_ADD:
@ -132,9 +132,11 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
} }
case OP_BREAK: case OP_BREAK:
printf("\t\tBreaking to the end of the loop; L%d\n", LoopEndLabel);
AsJmp(LoopEndLabel); AsJmp(LoopEndLabel);
return -1; return -1;
case OP_CONTINUE: case OP_CONTINUE:
printf("\t\tContinuing to the start of the loop; L%d\n", LoopBeginLabel);
AsJmp(LoopBeginLabel); AsJmp(LoopBeginLabel);
return -1; return -1;
@ -368,9 +370,8 @@ int AsIf(struct ASTNode* Node, int LoopStartLabel, int LoopEndLabel) {
if (Node->Right) if (Node->Right)
EndLabel = NewLabel(); EndLabel = NewLabel();
// Left is the condition // Left is the condition
AssembleTree(Node->Left, FalseLabel, -1, -1, Node->Operation); AssembleTree(Node->Left, FalseLabel, LoopStartLabel, LoopEndLabel, Node->Operation);
DeallocateAllRegisters(); DeallocateAllRegisters();
// Middle is the true block // Middle is the true block
@ -913,9 +914,14 @@ int AsCall(struct SymbolTableEntry* Entry, int Args) {
printf("\t\tCalling function %s with %d parameters\n", Entry->Name, Args); printf("\t\tCalling function %s with %d parameters\n", Entry->Name, Args);
printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]); printf("\t\t\tFunction returns into %s\n", Registers[OutRegister]);
// Allocate shadow space
fprintf(OutputFile, "\taddq\t$-32, %rsp\n");
fprintf(OutputFile, "\tcall\t%s\n", Entry->Name); fprintf(OutputFile, "\tcall\t%s\n", Entry->Name);
// Deallocate arguments and stack space.
if (Args > 4) if (Args > 4)
fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", 8 * (Args - 4)); fprintf(OutputFile, "\taddq\t$%d, %%rsp\n", (8 * (Args - 4)) + 32);
else
fprintf(OutputFile, "\taddq\t$32, %rsp\n");
fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]); fprintf(OutputFile, "\tmovq\t%%rax, %s\n", Registers[OutRegister]);

View File

@ -128,6 +128,8 @@ void Assemble(struct FileData* InputFile) {
exit(1); exit(1);
} }
InputFile->ObjectName = OutputName;
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName); snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName);
if (OptVerboseOutput) if (OptVerboseOutput)
printf("%s\n", Command); printf("%s\n", Command);
@ -152,8 +154,8 @@ void Assemble(struct FileData* InputFile) {
* *
*/ */
void Link(char* Output, struct FileData* Objects[]) { void Link(char* Output, struct FileData** Objects, int ObjectsLength) {
int Count, Size = TEXTLEN, Error; int Count, Size = TEXTLEN, Error, ObjectIdx = 0;
char Command[TEXTLEN], * CommandPtr; char Command[TEXTLEN], * CommandPtr;
CommandPtr = Command; CommandPtr = Command;
@ -161,11 +163,11 @@ void Link(char* Output, struct FileData* Objects[]) {
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
while (*Objects != NULL) { while (ObjectIdx < ObjectsLength - 1) {
Count = snprintf(CommandPtr, Size, "%s ", (*Objects)->ObjectName); Count = snprintf(CommandPtr, Size, "%s ", Objects[ObjectIdx]->ObjectName);
CommandPtr += Count; CommandPtr += Count;
Size -= Count; Size -= Count;
Objects++; ObjectIdx++;
} }
if (OptVerboseOutput) if (OptVerboseOutput)

View File

@ -6,7 +6,6 @@
#include <Defs.h> #include <Defs.h>
#include <Data.h> #include <Data.h>
#include <linux/limits.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@ -75,13 +74,22 @@
// Create a new file with the module name // Create a new file with the module name
struct FileData* ModuleData = malloc(sizeof(struct FileData)); struct FileData* ModuleData = malloc(sizeof(struct FileData));
memset(ModuleData, 0, sizeof(struct FileData));
ModuleData->AllowDefinitions = false; ModuleData->AllowDefinitions = false;
ModuleData->SourceName = ModulePath; ModuleData->SourceName = ModulePath;
printf("Swapping to module %s..\n\n", ModulePath); printf("Swapping to module %s..\n\n", ModulePath);
// Parse all relevant data from the module file... // Parse all relevant data from the module file...
Compile(ModuleData); if ((ModuleData->Stream = fopen(ModuleData->SourceName, "r")) == NULL) {
fprintf(stderr, "Unable to open %s: %s\n", ModuleData->SourceName, strerror(errno));
exit(1);
}
CurrentFile = ModuleData;
CurrentFile->CurrentLine = 1;
Tokenise();
ParseGlobals();
fclose(CurrentFile->Stream);
printf("\n\nSwapping back to file %s..\n", SavedFile->SourceName); printf("\n\nSwapping back to file %s..\n", SavedFile->SourceName);

View File

@ -97,7 +97,7 @@ int main(int argc, char* argv[]) {
// Option initialisers // Option initialisers
OptDumpTree = false; OptDumpTree = false;
OptKeepAssembly = true; OptKeepAssembly = true;
OptAssembleFiles = false; OptAssembleFiles = true;
OptLinkFiles = true; OptLinkFiles = true;
OptVerboseOutput = false; OptVerboseOutput = false;
@ -147,16 +147,21 @@ int main(int argc, char* argv[]) {
if (i >= argc) if (i >= argc)
DisplayUsage(argv[0]); DisplayUsage(argv[0]);
int StartOfFiles = i;
// Allocate enough files for the full specified source code // Allocate enough files for the full specified source code
Files = malloc(sizeof(struct FileData) * i); Files = malloc(sizeof(struct FileData*) * (argc - i) + 1);
memset(Files, 0, sizeof(struct FileData*) * (argc - i) + 1);
// For the rest of the files specified, we can iterate them right to left. // For the rest of the files specified, we can iterate them right to left.
while (i < argc) { while (i < argc) {
// Prepare the source metadata before we start compiling // Prepare the source metadata before we start compiling
struct FileData* Source = malloc(sizeof(struct FileData)); struct FileData* Source = malloc(sizeof(struct FileData));
memset(Source, 0, sizeof(struct FileData));
Source->SourceName = argv[i]; Source->SourceName = argv[i];
Source->AllowDefinitions = true; Source->AllowDefinitions = true;
Files[i] = Source; printf("Compiling file %d (%s)\n", i - StartOfFiles, argv[i]);
Files[i - StartOfFiles] = Source;
// Compile the file by invoking the Delegate // Compile the file by invoking the Delegate
Compile(Source); Compile(Source);
@ -164,12 +169,6 @@ int main(int argc, char* argv[]) {
// If we need to assemble (or link, which requires assembly) // If we need to assemble (or link, which requires assembly)
// then we invoke the Delegate again // then we invoke the Delegate again
Assemble(Source); Assemble(Source);
// We can only keep track of 99 objects, so we should crash at 98 to ensure we have enough room for the output file too.
if (ObjectCount == 98) {
fprintf(stderr, "Too many inputs");
return 1; // We use return because we're in main, rather than invoking Die.
}
} }
if (!OptKeepAssembly) if (!OptKeepAssembly)
@ -181,10 +180,10 @@ int main(int argc, char* argv[]) {
if (OptLinkFiles) { if (OptLinkFiles) {
// If needed, invoke the Delegate one last time. // If needed, invoke the Delegate one last time.
Link(OutputFileName, Files); Link(OutputFileName, Files, (argc - StartOfFiles) + 1);
if (!OptAssembleFiles) { if (!OptAssembleFiles) {
// Even though we need to assemble to link, we can respect the user's options and delete the intermediary files. // Even though we need to assemble to link, we can respect the user's options and delete the intermediary files.
for (i = 0; Files[i] != NULL; i++) { for (i = 0; i < (argc - StartOfFiles) + 1; i++) {
unlink(Files[i]->AssemblyName); unlink(Files[i]->AssemblyName);
unlink(Files[i]->ObjectName); unlink(Files[i]->ObjectName);
} }

View File

@ -256,7 +256,7 @@ struct ASTNode* ParseFunction(int Type) {
struct ASTNode* Tree; struct ASTNode* Tree;
struct ASTNode* FinalStatement; struct ASTNode* FinalStatement;
struct SymbolTableEntry* OldFunction, * NewFunction = NULL; struct SymbolTableEntry* OldFunction, * NewFunction = NULL;
int SymbolSlot, BreakLabel, ParamCount, ID; int BreakLabel = 0, ParamCount = 0;
if ((OldFunction = FindSymbol(CurrentIdentifier)) != NULL) if ((OldFunction = FindSymbol(CurrentIdentifier)) != NULL)
if (OldFunction->Storage != ST_FUNC) if (OldFunction->Storage != ST_FUNC)

View File

@ -11,6 +11,7 @@ int :: main() {
} }
if (x =? 10) { if (x =? 10) {
x = x + 2;
continue; continue;
} }