Fix break & continue implementation
This commit is contained in:
parent
0454c38a7e
commit
334b02cd76
|
@ -14,7 +14,6 @@
|
|||
#endif
|
||||
|
||||
#define TEXTLEN 512
|
||||
#define SYMBOLS 1024
|
||||
|
||||
// All currently open source files.
|
||||
extern_ struct FileData** Files;
|
||||
|
@ -60,5 +59,3 @@ extern_ int Overread;
|
|||
|
||||
extern_ char CurrentIdentifier[TEXTLEN + 1];
|
||||
|
||||
extern_ int CurrentGlobal;
|
||||
extern_ int CurrentLocal;
|
||||
|
|
|
@ -352,7 +352,7 @@ void Compile(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);
|
||||
|
||||
|
|
|
@ -79,9 +79,9 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
|
|||
return AsWhile(Node);
|
||||
|
||||
case OP_COMP:
|
||||
AssembleTree(Node->Left, -1, -1, -1, Node->Operation);
|
||||
AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||
DeallocateAllRegisters();
|
||||
AssembleTree(Node->Right, -1, -1, -1, Node->Operation);
|
||||
AssembleTree(Node->Right, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||
DeallocateAllRegisters();
|
||||
return -1;
|
||||
|
||||
|
@ -90,17 +90,17 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
|
|||
|
||||
case OP_FUNC:
|
||||
AsFunctionPreamble(Node->Symbol);
|
||||
AssembleTree(Node->Left, -1, -1, -1, Node->Operation);
|
||||
AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||
AsFunctionEpilogue(Node->Symbol);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (Node->Left)
|
||||
LeftVal = AssembleTree(Node->Left, -1, -1, -1, Node->Operation);
|
||||
LeftVal = AssembleTree(Node->Left, -1, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||
|
||||
if (Node->Right)
|
||||
RightVal = AssembleTree(Node->Right, LeftVal, -1, -1, Node->Operation);
|
||||
RightVal = AssembleTree(Node->Right, LeftVal, LoopBeginLabel, LoopEndLabel, Node->Operation);
|
||||
|
||||
switch (Node->Operation) {
|
||||
case OP_ADD:
|
||||
|
@ -132,9 +132,11 @@ int AssembleTree(struct ASTNode* Node, int Register, int LoopBeginLabel, int Loo
|
|||
}
|
||||
|
||||
case OP_BREAK:
|
||||
printf("\t\tBreaking to the end of the loop; L%d\n", LoopEndLabel);
|
||||
AsJmp(LoopEndLabel);
|
||||
return -1;
|
||||
case OP_CONTINUE:
|
||||
printf("\t\tContinuing to the start of the loop; L%d\n", LoopBeginLabel);
|
||||
AsJmp(LoopBeginLabel);
|
||||
return -1;
|
||||
|
||||
|
@ -368,9 +370,8 @@ int AsIf(struct ASTNode* Node, int LoopStartLabel, int LoopEndLabel) {
|
|||
if (Node->Right)
|
||||
EndLabel = NewLabel();
|
||||
|
||||
|
||||
// Left is the condition
|
||||
AssembleTree(Node->Left, FalseLabel, -1, -1, Node->Operation);
|
||||
AssembleTree(Node->Left, FalseLabel, LoopStartLabel, LoopEndLabel, Node->Operation);
|
||||
DeallocateAllRegisters();
|
||||
|
||||
// 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\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);
|
||||
// Deallocate arguments and stack space.
|
||||
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]);
|
||||
|
||||
|
|
|
@ -128,6 +128,8 @@ void Assemble(struct FileData* InputFile) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
InputFile->ObjectName = OutputName;
|
||||
|
||||
snprintf(Command, TEXTLEN, "%s %s %s", "as -o ", OutputName, InputFile->AssemblyName);
|
||||
if (OptVerboseOutput)
|
||||
printf("%s\n", Command);
|
||||
|
@ -152,8 +154,8 @@ void Assemble(struct FileData* InputFile) {
|
|||
*
|
||||
*/
|
||||
|
||||
void Link(char* Output, struct FileData* Objects[]) {
|
||||
int Count, Size = TEXTLEN, Error;
|
||||
void Link(char* Output, struct FileData** Objects, int ObjectsLength) {
|
||||
int Count, Size = TEXTLEN, Error, ObjectIdx = 0;
|
||||
char Command[TEXTLEN], * CommandPtr;
|
||||
|
||||
CommandPtr = Command;
|
||||
|
@ -161,11 +163,11 @@ void Link(char* Output, struct FileData* Objects[]) {
|
|||
CommandPtr += Count;
|
||||
Size -= Count;
|
||||
|
||||
while (*Objects != NULL) {
|
||||
Count = snprintf(CommandPtr, Size, "%s ", (*Objects)->ObjectName);
|
||||
while (ObjectIdx < ObjectsLength - 1) {
|
||||
Count = snprintf(CommandPtr, Size, "%s ", Objects[ObjectIdx]->ObjectName);
|
||||
CommandPtr += Count;
|
||||
Size -= Count;
|
||||
Objects++;
|
||||
ObjectIdx++;
|
||||
}
|
||||
|
||||
if (OptVerboseOutput)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include <Defs.h>
|
||||
#include <Data.h>
|
||||
#include <linux/limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
@ -75,13 +74,22 @@
|
|||
|
||||
// Create a new file with the module name
|
||||
struct FileData* ModuleData = malloc(sizeof(struct FileData));
|
||||
memset(ModuleData, 0, sizeof(struct FileData));
|
||||
ModuleData->AllowDefinitions = false;
|
||||
ModuleData->SourceName = ModulePath;
|
||||
|
||||
printf("Swapping to module %s..\n\n", ModulePath);
|
||||
|
||||
// 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);
|
||||
|
||||
|
|
21
src/Main.c
21
src/Main.c
|
@ -97,7 +97,7 @@ int main(int argc, char* argv[]) {
|
|||
// Option initialisers
|
||||
OptDumpTree = false;
|
||||
OptKeepAssembly = true;
|
||||
OptAssembleFiles = false;
|
||||
OptAssembleFiles = true;
|
||||
OptLinkFiles = true;
|
||||
OptVerboseOutput = false;
|
||||
|
||||
|
@ -147,16 +147,21 @@ int main(int argc, char* argv[]) {
|
|||
if (i >= argc)
|
||||
DisplayUsage(argv[0]);
|
||||
|
||||
int StartOfFiles = i;
|
||||
// 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.
|
||||
while (i < argc) {
|
||||
// Prepare the source metadata before we start compiling
|
||||
struct FileData* Source = malloc(sizeof(struct FileData));
|
||||
memset(Source, 0, sizeof(struct FileData));
|
||||
Source->SourceName = argv[i];
|
||||
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(Source);
|
||||
|
@ -164,12 +169,6 @@ int main(int argc, char* argv[]) {
|
|||
// If we need to assemble (or link, which requires assembly)
|
||||
// then we invoke the Delegate again
|
||||
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)
|
||||
|
@ -181,10 +180,10 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
if (OptLinkFiles) {
|
||||
// If needed, invoke the Delegate one last time.
|
||||
Link(OutputFileName, Files);
|
||||
Link(OutputFileName, Files, (argc - StartOfFiles) + 1);
|
||||
if (!OptAssembleFiles) {
|
||||
// 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]->ObjectName);
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ struct ASTNode* ParseFunction(int Type) {
|
|||
struct ASTNode* Tree;
|
||||
struct ASTNode* FinalStatement;
|
||||
struct SymbolTableEntry* OldFunction, * NewFunction = NULL;
|
||||
int SymbolSlot, BreakLabel, ParamCount, ID;
|
||||
int BreakLabel = 0, ParamCount = 0;
|
||||
|
||||
if ((OldFunction = FindSymbol(CurrentIdentifier)) != NULL)
|
||||
if (OldFunction->Storage != ST_FUNC)
|
||||
|
|
|
@ -11,6 +11,7 @@ int :: main() {
|
|||
}
|
||||
|
||||
if (x =? 10) {
|
||||
x = x + 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user