diff --git a/include/Defs.h b/include/Defs.h index 846d3b4..7f734da 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -361,15 +361,19 @@ int AsMul(int Left, int Right); int AsSub(int Left, int Right); int AsDiv(int Left, int Right); -int AsLdVar(int ID, int Operation); -int AsStrVar(int Register, int ID); +int AsLdGlobalVar(int ID, int Operation); +int AsLdLocalVar(int ID, int Operation); +int AsStrGlobalVar(int Register, int ID); +int AsStrLocalVar(int Register, int ID); +int AsCalcOffset(int Type, int Param); +void AsNewStackFrame(); int AsDeref(int Reg, int Type); int AsStrDeref(int Register1, int Register2, int Type); int AsAddr(int ID); -void AsNewSymb(int ID); +void AsGlobalSymbol(int ID); int AsNewString(char* Value); diff --git a/src/Assembler.c b/src/Assembler.c index 83ac411..bcd91d7 100644 --- a/src/Assembler.c +++ b/src/Assembler.c @@ -114,7 +114,12 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { if(Node->Right == NULL) Die("Fault in assigning a null rvalue"); switch(Node->Right->Operation) { - case REF_IDENT: return AsStrVar(LeftVal, Node->Right->Value.ID); + case REF_IDENT: + if(Symbols[Node->Value.ID].Storage == SC_LOCAL) + return AsStrLocalVar(Node->Value.ID, Node->Operation); + else + return AsStrGlobalVar(Node->Value.ID, Node->Operation); + case OP_DEREF: return AsStrDeref(LeftVal, RightVal, Node->Right->ExprType); default: DieDecimal("Can't ASSIGN in AssembleTree: ", Node->Operation); } @@ -162,9 +167,12 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { case REF_IDENT: - if(Node->RVal || ParentOp == OP_DEREF) - return AsLdVar(Node->Value.ID, Node->Operation); - else + if(Node->RVal || ParentOp == OP_DEREF) { + if(Symbols[Node->Value.ID].Storage == SC_LOCAL) + return AsLdLocalVar(Node->Value.ID, Node->Operation); + else + return AsLdGlobalVar(Node->Value.ID, Node->Operation); + } else return -1; case TERM_INTLITERAL: @@ -199,16 +207,16 @@ int AssembleTree(struct ASTNode* Node, int Register, int ParentOp) { return AsShiftRight(LeftVal, RightVal); case OP_POSTINC: - return AsLdVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); case OP_POSTDEC: - return AsLdVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); case OP_PREINC: - return AsLdVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); case OP_PREDEC: - return AsLdVar(Node->Value.IntValue, Node->Operation); + return AsLdGlobalVar(Node->Value.IntValue, Node->Operation); case OP_BOOLNOT: return AsBooleanNOT(LeftVal); @@ -455,7 +463,7 @@ int AsShl(int Register, int Val) { int AsLdGlobalVar(int ID, int Operation) { int Reg = RetrieveRegister(); - printf("\tStoring %s's contents into %s\n", Symbols[ID].Name, Registers[Reg]); + printf("\tStoring %s's contents into %s, globally\n", Symbols[ID].Name, Registers[Reg]); switch(Symbols[ID].Type) { case RET_CHAR: @@ -526,7 +534,7 @@ int AsLdGlobalVar(int ID, int Operation) { } int AsStrGlobalVar(int Register, int ID) { - printf("\tStoring contents of %s into %s, type %d\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type); + printf("\tStoring contents of %s into %s, type %d, globally: ID %d\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type, ID); switch(Symbols[ID].Type) { case RET_CHAR: @@ -556,7 +564,7 @@ int AsStrGlobalVar(int Register, int ID) { int AsLdLocalVar(int ID, int Operation) { int Reg = RetrieveRegister(); - printf("\tStoring the var at %d's contents into %s\n", Symbols[ID].SinkOffset, Registers[Reg]); + printf("\tStoring the var at %d's contents into %s, locally\n", Symbols[ID].SinkOffset, Registers[Reg]); switch(Symbols[ID].Type) { case RET_CHAR: @@ -627,7 +635,7 @@ int AsLdLocalVar(int ID, int Operation) { } int AsStrLocalVar(int Register, int ID) { - printf("\tStoring contents of %s into %s, type %d\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type); + printf("\tStoring contents of %s into %s, type %d, locally\n", Registers[Register], Symbols[ID].Name, Symbols[ID].Type); switch(Symbols[ID].Type) { case RET_CHAR: @@ -698,7 +706,7 @@ int AsStrDeref(int Register1, int Register2, int Type) { return Register1; } -void AsNewSymb(int ID) { +void AsGlobalSymbol(int ID) { int TypeSize; TypeSize = PrimitiveSize(Symbols[ID].Type); @@ -878,6 +886,8 @@ void AssemblerPreamble() { void AsFunctionPreamble(int FunctionID) { char* Name = Symbols[FunctionID].Name; + StackFrameOffset = (LocalVarOffset + 15) & ~15; + fprintf(OutputFile, "\t.text\n" "\t.globl\t%s\n" @@ -885,7 +895,7 @@ void AsFunctionPreamble(int FunctionID) { "%s:\n" "\tpushq\t%%rbp\n" "\tmovq\t%%rsp, %%rbp\n" - "\tsubq\t$32, %%rsp\n", Name, Name, Name); + "\taddq\t%d, %%rsp\n", Name, Name, Name, -StackFrameOffset); //PECOFF requires we call the global initialisers if(!strcmp(Name, "main")) @@ -895,9 +905,9 @@ void AsFunctionPreamble(int FunctionID) { void AsFunctionEpilogue(int FunctionID) { AsLabel(Symbols[FunctionID].EndLabel); - fputs( + fprintf(OutputFile, "\tpopq\t%rbp\n" - "\taddq\t$32, %rsp\n" + "\taddq\t%d, %rsp\n" "\tret\n", - OutputFile); + StackFrameOffset); } \ No newline at end of file diff --git a/src/Main.c b/src/Main.c index ec241f1..a6e8d7f 100644 --- a/src/Main.c +++ b/src/Main.c @@ -82,6 +82,8 @@ char* TypeNames[9] = { "none", "char", "int", "long", "void", "charptr", "intpt int main(int argc, char* argv[]) { Line = 1; Overread = '\n'; + CurrentGlobal = 0; + CurrentLocal = SYMBOLS - 1; struct ASTNode* Node; diff --git a/src/Statements.c b/src/Statements.c index d2eee00..8cf8e25 100644 --- a/src/Statements.c +++ b/src/Statements.c @@ -31,21 +31,14 @@ void BeginVariableDeclaration(int Type, int Scope) { //Type = Type - 2; if(CurrentToken.type == LI_INT) { printf("Adding array %s that is %d x %s.\r\n", CurrentIdentifier, CurrentToken.value, TypeNames[Type]); - if(Scope == SC_LOCAL) { - AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, SC_LOCAL, 0, CurrentToken.value); - } else if(Scope == SC_GLOBAL) { - AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, SC_GLOBAL, 0, CurrentToken.value); - } + AddSymbol(CurrentIdentifier, PointerTo(Type), ST_ARR, Scope, 0, CurrentToken.value); } Tokenise(&CurrentToken); VerifyToken(LI_RBRAS, "]"); } else { - if(Scope == SC_LOCAL) { - AddSymbol(CurrentIdentifier, Type, ST_VAR, SC_LOCAL, 0, 1); - } else if(Scope == SC_GLOBAL) { - AddSymbol(CurrentIdentifier, Type, ST_VAR, SC_GLOBAL, 0, 1); - } + printf("Adding var %s that is a %s\r\n", CurrentIdentifier, TypeNames[Type]); + AddSymbol(CurrentIdentifier, Type, ST_VAR, Scope, 0, 1); } VerifyToken(LI_SEMIC, ";"); diff --git a/src/Symbols.c b/src/Symbols.c index 10760c8..7b6918e 100644 --- a/src/Symbols.c +++ b/src/Symbols.c @@ -13,13 +13,20 @@ static int GlobalSymbols = 0; int FindSymbolImpl(char* Symbol, int Storage) { int Ind; - for(Ind = 0; Ind < (Storage == SC_GLOBAL /* Are we global scope? */ + for(Ind = (Storage == SC_GLOBAL /* Are we global scope? */ + ? 0 /* If so, start from the beginning */ + : CurrentLocal + 1 /* Else, go from the start of the local block */ + ); + Ind < (Storage == SC_GLOBAL /* Are we global scope? */ ? CurrentGlobal /* If so, start searching at the start */ : SYMBOLS /* Otherwise, start at the end and work backward */ - ); Ind++) { + ); + Ind++) { - if(*Symbol == *Symbols[Ind].Name && !strcmp(Symbol, Symbols[Ind].Name)) + if(*Symbol == *Symbols[Ind].Name && !strcmp(Symbol, Symbols[Ind].Name)) { + printf("\t\tFound %s at %d\r\n", Symbol, Ind); return Ind; + } } return -1; @@ -52,8 +59,10 @@ int FindSymbol(char* Symbol) { static int NewGlobalSymbol() { int Pos; - if((Pos = (CurrentGlobal++)) >= CurrentLocal) + if((Pos = (CurrentGlobal++)) >= CurrentLocal) { + printf("%d:%d\r\n", CurrentGlobal, CurrentLocal); Die("Too many Global symbols"); + } return Pos; } @@ -97,10 +106,12 @@ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, in // we can use this switch to avoid duplicated code. switch(Storage) { case SC_GLOBAL: + printf("\tCreating new global symbol %s\r\n", Name); TableSlot = NewGlobalSymbol(); AsGlobalSymbol(TableSlot); break; case SC_LOCAL: + printf("\tCreating new local symbol %s\r\n", Name); TableSlot = NewLocalSymbol(); SinkOffset = AsCalcOffset(Type, 0); break; diff --git a/tests/locals b/tests/locals new file mode 100644 index 0000000..22df4cf --- /dev/null +++ b/tests/locals @@ -0,0 +1,10 @@ +int a; int b; int c; + +int :: main() +{ + char z; int y; int x; + x= 10; y= 20; z= 30; + a= 5; b= 15; c= 25; + + return(0); +} \ No newline at end of file