/*************/ /*GEMWIRE */ /* ERYTHRO*/ /*************/ #include #include static int GlobalSymbols = 0; int FindSymbolImpl(char* Symbol, int Storage) { int Ind; 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++) { if(Storage == SC_GLOBAL && Symbols[Ind].Storage == SC_PARAM) continue; // Skip searching globals for parameters. if(*Symbol == *Symbols[Ind].Name && !strcmp(Symbol, Symbols[Ind].Name)) { printf("\t\tFound %s at %d\r\n", Symbol, Ind); return Ind; } } return -1; } /* * Find the position of a symbol in the symbol table. * @Return the index into the symbol table if found, * -1 if not found. * Does not care about differentiating local or global. * It will only be consistent. */ int FindSymbol(char* Symbol) { int Res; // Prioritise local vars if((Res = FindSymbolImpl(Symbol, SC_LOCAL)) == -1) // Fallback to global vars. return FindSymbolImpl(Symbol, SC_GLOBAL); return Res; } /* * Append a new entry to the table of global symbols. * @Return the index to the new entry * * Will kill the program if we run out. * The death condition here is running into the local symbol table. * //TODO: Dump symbols on death? */ static int NewGlobalSymbol() { int Pos; if((Pos = (CurrentGlobal++)) >= CurrentLocal) { printf("%d:%d\r\n", CurrentGlobal, CurrentLocal); Die("Too many Global symbols"); } return Pos; } /* * Append a new entry to the table of local (function-local) symbols. * @Return the index to the new entry * * Will kill the program if we run out. * The death condition here is running into the global symbol table. * //TODO: Dump symbols on death? */ static int NewLocalSymbol() { int Pos; if((Pos = (CurrentLocal--)) <= CurrentGlobal) Die("Too many Local symbols"); return Pos; } /* * Reset the local counter on functions. */ void FreeLocals() { CurrentLocal = SYMBOLS - 1; } /* * Add a symbol to the tables, and set all the metadata. * @param Name: The string representing the name of the symbol. * @param Type: The return type in terms of DataTypes enum values. * @param Structure: The type of symbol this is, in terms of StructureType enum. * @param Storage: The storage scope of this symbol. For functions this is always SC_GLOBAL (for now). Vars and Arrays can be GLOBAL or SC_LOCAL. * @param EndLabel: The label # to jump to to exit the function or array, where appropriate. * @param Length: The size of the struct/array in units of 1xbase * * @return The ID in the symbol table that now represents this symbol. */ int AddSymbol(char* Name, int Type, int Structure, int Storage, int EndLabel, int Length) { int TableSlot; int SinkOffset = 0; if((TableSlot = FindSymbolImpl(Name, Storage)) != -1) return -1; // Instaed of spliting this up into AddLocalSymbol and AddGlobalSymbol, // we can use this switch to avoid duplicated code. switch(Storage) { case SC_PARAM: // Instead of special casing parameters, we can just add these to the symbol lists and be done with it. printf("\tPreparing new parameter %s of type %s\r\n", Name, TypeNames[Type]); TableSlot = AddSymbol(Name, Type, Structure, SC_GLOBAL, 88, 1); Symbols[TableSlot].Storage = SC_PARAM; // Fix the parameter after running the global process TableSlot = AddSymbol(Name, Type, Structure, SC_LOCAL, 88, 1); Symbols[TableSlot].Storage = SC_PARAM; // Fix the parameter after running the local process return TableSlot; case SC_GLOBAL: TableSlot = NewGlobalSymbol(); break; case SC_LOCAL: printf("\tCreating new local symbol %s\r\n", Name); TableSlot = NewLocalSymbol(); SinkOffset = AsCalcOffset(Type); break; } Symbols[TableSlot].Name = strdup(Name); Symbols[TableSlot].Type = Type; Symbols[TableSlot].Structure = Structure; Symbols[TableSlot].Storage = Storage; Symbols[TableSlot].Length = Length; Symbols[TableSlot].SinkOffset = SinkOffset; Symbols[TableSlot].EndLabel = EndLabel; // NOTE: Generating global symbol names must happen AFTER the name and type are declared. switch(Storage) { case SC_GLOBAL: printf("\tCreating new global symbol %s into slot %d\r\n", Name, TableSlot); if(Structure != ST_FUNC && EndLabel != 88) { // Magic keyword so that we don't generate ASM globals for parameters printf("\t\tGenerating data symbol.\r\n"); AsGlobalSymbol(TableSlot); } break; case SC_LOCAL: break; } //printf("Adding new variable %s of type %s to the table at %d\n", CurrentIdentifier, Types[Type], TableSlot); return TableSlot; }