Added Compact Encoding (-c)

Added second pass optimization (-h)
This commit is contained in:
David Anderson 2004-08-11 14:31:26 +00:00
parent c9a0a3f9be
commit 81b3e662cf
5 changed files with 291 additions and 42 deletions

View File

@ -29,6 +29,8 @@ Compiler::Compiler()
Output = 0; Output = 0;
stacksize = cellsize * 4096; stacksize = cellsize * 4096;
debug = false; debug = false;
pack = false;
dopt = false;
Init(); Init();
} }
@ -53,9 +55,20 @@ Compiler::Compiler(std::string &f)
filename.assign(f); filename.assign(f);
stacksize = cellsize * 4096; stacksize = cellsize * 4096;
debug = false; debug = false;
pack = false;
dopt = false;
Init(); Init();
} }
bool Compiler::SetDOpt()
{
bool state = dopt;
dopt = dopt ? false : true;
return state;
}
bool Compiler::SetDebug() bool Compiler::SetDebug()
{ {
bool state = debug; bool state = debug;
@ -65,6 +78,15 @@ bool Compiler::SetDebug()
return state; return state;
} }
bool Compiler::SetPack()
{
bool state = pack;
pack = pack ? false : true;
return state;
}
void Compiler::Load(std::string &f) void Compiler::Load(std::string &f)
{ {
filename.assign(f); filename.assign(f);
@ -111,6 +133,49 @@ int Compiler::CipCount()
return cipc; return cipc;
} }
void Compiler::WriteCell(FILE *fp, ucell *c, int repeat)
{
unsigned char T[5] = {0,0,0,0,0};
unsigned char code = 0;
int index = 0;
ucell p = (*c);
int i = 0;
for (i=1; i<=repeat; i++)
{
if (pack)
{
for (index=0;index<5;index++)
{
T[index]=(unsigned char)(p & 0x7f);
p>>=7;
}
while (index>1 && T[index-1]==0 && (T[index-2] & 0x40)==0)
{
index--;
}
if (index==5 && T[index-1]==0x0f && (T[index-2] & 0x40)!=0)
{
index--;
}
while (index>1 && T[index-1]==0x7f && (T[index-2] & 0x40)!=0)
{
index--;
}
assert(index>0);
while (index-->0)
{
code=(unsigned char)((index==0)?T[index]:(T[index]|0x80));
fwrite((void*)&code, sizeof(unsigned char), 1, fp);
bitsOut += sizeof(unsigned char);
}
} else {
fwrite((void*)c, sizeof(ucell), 1, fp);
bitsOut += sizeof(ucell);
}
}
}
bool Compiler::Compile(std::string &out) bool Compiler::Compile(std::string &out)
{ {
if (CodeList.size() < 1 || !CError || CError->GetStatus() >= Err_Error) if (CodeList.size() < 1 || !CError || CError->GetStatus() >= Err_Error)
@ -118,6 +183,7 @@ bool Compiler::Compile(std::string &out)
return false; return false;
} }
bitsOut = 0;
int32_t fileSize = 0; int32_t fileSize = 0;
int16_t magic = (int16_t)AMX_MAGIC; int16_t magic = (int16_t)AMX_MAGIC;
char file_version = CUR_FILE_VERSION; char file_version = CUR_FILE_VERSION;
@ -127,6 +193,15 @@ bool Compiler::Compile(std::string &out)
int32_t cod, dat, hea, stp, cip, publics, natives, libraries; int32_t cod, dat, hea, stp, cip, publics, natives, libraries;
int32_t pubvars, tags, names; int32_t pubvars, tags, names;
int hdrEnd = sizeof(AMX_HEADER); int hdrEnd = sizeof(AMX_HEADER);
if (debug)
{
flags |= AMX_FLAG_DEBUG;
}
if (pack)
{
flags |= AMX_FLAG_COMPACT;
}
std::vector<ProcMngr::AsmProc *> ProcList; std::vector<ProcMngr::AsmProc *> ProcList;
std::vector<ProcMngr::AsmProc *>::iterator pl; std::vector<ProcMngr::AsmProc *>::iterator pl;
@ -195,6 +270,7 @@ bool Compiler::Compile(std::string &out)
cOffset += (int)strlen(Nametbl.at(off).Name) + 1; cOffset += (int)strlen(Nametbl.at(off).Name) + 1;
} }
bitsOut = cOffset;
cod = cOffset; cod = cOffset;
dat = cod + CipCount(); dat = cod + CipCount();
hea = dat + DAT->GetSize(); hea = dat + DAT->GetSize();
@ -267,15 +343,15 @@ bool Compiler::Compile(std::string &out)
std::vector<Asm *>::iterator ci; std::vector<Asm *>::iterator ci;
std::vector<int>::iterator di; std::vector<int>::iterator di;
int cop = 0; ucell cop = 0;
for (ci = CodeList.begin(); ci != CodeList.end(); ci++) for (ci = CodeList.begin(); ci != CodeList.end(); ci++)
{ {
cop = (*ci)->op; cop = (*ci)->op;
fwrite((void *)&cop, sizeof(int32_t), 1, fp); WriteCell(fp, &cop, 1);
for (di = (*ci)->params.begin(); di != (*ci)->params.end(); di++) for (di = (*ci)->params.begin(); di != (*ci)->params.end(); di++)
{ {
cop = (*di); cop = (*di);
fwrite((void *)&cop, sizeof(int32_t), 1, fp); WriteCell(fp, &cop, 1);
} }
} }
@ -283,7 +359,7 @@ bool Compiler::Compile(std::string &out)
std::vector<DataMngr::Datum *>::iterator dmi; std::vector<DataMngr::Datum *>::iterator dmi;
DAT->GetData(dm); DAT->GetData(dm);
int val = 0; ucell val = 0;
const char *s = 0; const char *s = 0;
for (dmi = dm.begin(); dmi != dm.end(); dmi++) for (dmi = dm.begin(); dmi != dm.end(); dmi++)
{ {
@ -298,18 +374,25 @@ bool Compiler::Compile(std::string &out)
for (int q = 0; q < (*dmi)->e.Size(); q++) for (int q = 0; q < (*dmi)->e.Size(); q++)
{ {
val = s[q]; val = s[q];
fwrite((void*)&val, sizeof(int32_t), 1, fp); WriteCell(fp, &val, 1);
} }
} }
} else { } else {
char c = (*dmi)->fill; if (DAT->IsOptimized())
for (int iter=0; iter<=(*dmi)->e.GetNumber(); iter++) break;
{ ucell c = (*dmi)->fill;
fwrite((void*)&c, sizeof(int32_t), 1, fp); WriteCell(fp, &c, (*dmi)->e.GetNumber());
}
} }
} }
/* Was packing enabled? Re-output the actual size */
if (pack)
{
fseek(fp, 0, SEEK_SET);
fwrite((void *)&bitsOut, sizeof(int32_t), 1, fp);
fseek(fp, 0, SEEK_END);
}
fclose(fp); fclose(fp);
return true; return true;
@ -326,32 +409,44 @@ void Compiler::Clear()
CSymbols->Clear(); CSymbols->Clear();
} }
/* Two pass parser.
* The first pass applies macros + defines + directives
* natives, and data.
* The second pass eats up everything else (code, publics)
*/
bool Compiler::Parse() bool Compiler::Parse()
{ {
std::ifstream fp(filename.c_str()); FILE *fp = 0;
char buffer[256] = {0}; char buffer[256] = {0};
std::stack<int> DefStack; std::stack<int> DefStack;
std::stack<std::string> LabelStack; std::stack<std::string> LabelStack;
curLine = 0; curLine = 0;
AsmSection sec = Asm_None; AsmSection sec = Asm_None;
lastCip = 0-cellsize; lastCip = 0-cellsize;
int pass = 0;
if (!fp.is_open()) Start:
fp = fopen(filename.c_str(), "rt");
curLine = 0;
sec = Asm_None;
lastCip = 0-cellsize;
if (!fp)
{ {
CError->ErrorMsg(Err_FileOpen, filename.c_str()); CError->ErrorMsg(Err_FileOpen, filename.c_str());
return false; return false;
} }
while (!fp.eof()) while (!feof(fp))
{ {
fp.getline(buffer, 255); fgets(buffer, 255, fp);
curLine+=1; curLine+=1;
/* Check for preprocessor directives */ /* Check for preprocessor directives */
if (buffer[0] == '#') if (buffer[0] == '#')
{ {
std::string procline(buffer); std::string procline(buffer);
if (procline.substr(0, 3).compare("#if") == 0) if (procline.substr(0, 6).compare("#ifdef") == 0)
{ {
std::string def; std::string def;
std::string temp; std::string temp;
@ -359,16 +454,37 @@ bool Compiler::Parse()
StringBreak(procline, def, temp); StringBreak(procline, def, temp);
StringBreak(temp, def, comp); StringBreak(temp, def, comp);
DefineMngr::Define *D = 0; DefineMngr::Define *D = 0;
if ((D = CDefines->FindDefine(def)) == 0) if ( (D = CDefines->FindDefine(def)) == NULL)
{ {
DefStack.push(0); DefStack.push(0);
} else if (D->GetDefine()->compare(comp) == 0) { } else {
if (D->GetDefine()->compare("0") == 0)
{
DefStack.push(0);
} else {
DefStack.push(1);
}
}
} else if (procline.substr(0, 7).compare("#ifndef") == 0) {
std::string def;
std::string temp;
std::string comp;
StringBreak(procline, def, temp);
StringBreak(temp, def, comp);
DefineMngr::Define *D = 0;
if ( (D = CDefines->FindDefine(def)) == NULL)
{
DefStack.push(1); DefStack.push(1);
} else { } else {
DefStack.push(0); if (D->GetDefine()->compare("0") == 0)
{
DefStack.push(1);
} else {
DefStack.push(0);
}
} }
} else if (procline.substr(0, 5).compare("#else") == 0) { } else if (procline.substr(0, 5).compare("#else") == 0) {
if (DefStack.size()) if (!DefStack.empty())
{ {
if (DefStack.top() == 1) if (DefStack.top() == 1)
{ {
@ -383,7 +499,7 @@ bool Compiler::Parse()
} }
continue; continue;
} else if (procline.substr(0, 6).compare("#endif") == 0) { } else if (procline.substr(0, 6).compare("#endif") == 0) {
if (DefStack.size()) if (!DefStack.empty())
{ {
DefStack.pop(); DefStack.pop();
} else { } else {
@ -399,7 +515,11 @@ bool Compiler::Parse()
continue; continue;
} }
} }
ProcessDirective(procline); // only process directives on pass one
if (pass == 0)
{
ProcessDirective(procline);
}
} }
continue; continue;
} }
@ -428,7 +548,7 @@ bool Compiler::Parse()
if (line.compare(".DATA") == 0) if (line.compare(".DATA") == 0)
{ {
sec = Asm_Data; sec = Asm_Data;
} else if (line.compare(".CODE") == 0) { } else if (line.compare(".CODE") == 0) {;
sec = Asm_Code; sec = Asm_Code;
} else if (line.compare(".PUBLIC") == 0) { } else if (line.compare(".PUBLIC") == 0) {
sec = Asm_Public; sec = Asm_Public;
@ -438,13 +558,16 @@ bool Compiler::Parse()
sec = Asm_Invalid; sec = Asm_Invalid;
CError->ErrorMsg(Err_Invalid_Section, buffer); CError->ErrorMsg(Err_Invalid_Section, buffer);
} }
/* Update the labels */ if (pass == 1)
CLabels->CompleteQueue(true);
while (!LabelStack.empty())
{ {
CLabels->EraseLabel(LabelStack.top()); /* Update the labels */
CSymbols->EraseSymbol(LabelStack.top()); CLabels->CompleteQueue(true);
LabelStack.pop(); while (!LabelStack.empty())
{
CLabels->EraseLabel(LabelStack.top());
CSymbols->EraseSymbol(LabelStack.top());
LabelStack.pop();
}
} }
} else { } else {
/* Do pre-processing */ /* Do pre-processing */
@ -461,6 +584,8 @@ bool Compiler::Parse()
} else if (sec == Asm_Invalid) { } else if (sec == Asm_Invalid) {
/* Just ignore it */ /* Just ignore it */
} else if (sec == Asm_Data) { } else if (sec == Asm_Data) {
if (pass == 1)
continue;
/* Format is Symbol, [db|stat], Data */ /* Format is Symbol, [db|stat], Data */
std::string symbol; std::string symbol;
std::string data; std::string data;
@ -505,17 +630,17 @@ bool Compiler::Parse()
CExpr t(CError); CExpr t(CError);
t.Set(fill); t.Set(fill);
t.Evaluate(); t.Evaluate();
e.Set(amt); e = EvalE(amt, Sym_None);
e.Evaluate();
DAT->Add(symbol, e, false, t.GetNumber()); DAT->Add(symbol, e, false, t.GetNumber());
} else { } else {
e.Set(data); e = EvalE(data, Sym_None);
e.Evaluate();
DAT->Add(symbol, e, false, 0); DAT->Add(symbol, e, false, 0);
} }
} }
CSymbols->AddSymbol(symbol, Sym_Dat, CurLine()); CSymbols->AddSymbol(symbol, Sym_Dat, CurLine());
} else if (sec == Asm_Public) { } else if (sec == Asm_Public) {
if (pass == 0)
continue;
if (!IsValidSymbol(line)) if (!IsValidSymbol(line))
{ {
CError->ErrorMsg(Err_Invalid_Symbol); CError->ErrorMsg(Err_Invalid_Symbol);
@ -538,6 +663,8 @@ bool Compiler::Parse()
continue; continue;
} }
} else if (sec == Asm_Native) { } else if (sec == Asm_Native) {
if (pass == 1)
continue;
if (!IsValidSymbol(line)) if (!IsValidSymbol(line))
{ {
CError->ErrorMsg(Err_Invalid_Symbol); CError->ErrorMsg(Err_Invalid_Symbol);
@ -552,6 +679,8 @@ bool Compiler::Parse()
S = CSymbols->AddSymbol(line, Sym_Native, CurLine()); S = CSymbols->AddSymbol(line, Sym_Native, CurLine());
CNatives->AddNative(S); CNatives->AddNative(S);
} else if (sec == Asm_Code) { } else if (sec == Asm_Code) {
if (pass == 0)
continue;
std::string code; std::string code;
std::string params; std::string params;
SymbolList::Symbol *S; SymbolList::Symbol *S;
@ -1454,12 +1583,25 @@ bool Compiler::Parse()
} /* Line processing */ } /* Line processing */
} /* While */ } /* While */
// go for second pass
if (pass == 0)
{
pass = 1;
fclose(fp);
if (dopt)
DAT->Optimize();
goto Start;
}
/* We're not done! Check the label Queue */ /* We're not done! Check the label Queue */
CLabels->CompleteQueue(); CLabels->CompleteQueue();
CError->PrintReport(); CError->PrintReport();
if (CError->GetStatus() >= Err_Error) if (CError->GetStatus() >= Err_Error)
{
return false; return false;
}
return true; return true;
} }
@ -1882,13 +2024,22 @@ void Compiler::ProcessDirective(std::string &text)
} }
} }
int Compiler::Eval(std::string &str, SymbolType sym)
{
CExpr e(CError);
e = EvalE(str, sym);
return e.GetNumber();
}
/* The evaluator works by storing expressions on a stack. /* The evaluator works by storing expressions on a stack.
Each expression is an RPN-ordered pair of lists for ops and values Each expression is an RPN-ordered pair of lists for ops and values
Every time the stack is popped, the expression is evaluated by searching Every time the stack is popped, the expression is evaluated by searching
for the highest operators and evaluating them. for the highest operators and evaluating them.
Note that string literals are not allowed here yet. Note that string literals are not allowed here yet.
*/ */
int Compiler::Eval(std::string &str, SymbolType sym) CExpr Compiler::EvalE(std::string &str, SymbolType sym)
{ {
std::stack<rpn *> Stack; std::stack<rpn *> Stack;
std::string bpstr; std::string bpstr;
@ -2025,7 +2176,7 @@ int Compiler::Eval(std::string &str, SymbolType sym)
delete r; delete r;
r = 0; r = 0;
return final.GetNumber(); return final;
} }
CExpr Compiler::EvalRpn(rpn *r, SymbolType sym) CExpr Compiler::EvalRpn(rpn *r, SymbolType sym)

View File

@ -68,16 +68,20 @@ public:
int CurCip() { return lastCip; } int CurCip() { return lastCip; }
Asm *CurAsm() { return curAsm; } Asm *CurAsm() { return curAsm; }
bool SetDebug(); bool SetDebug();
public: //private bool SetPack();
bool SetDOpt();
int DerefSymbol(std::string &str, SymbolType sym = Sym_None); int DerefSymbol(std::string &str, SymbolType sym = Sym_None);
bool IsSymbol(std::string &str);
private:
void ProcessDirective(std::string &text); void ProcessDirective(std::string &text);
void Init(); void Init();
void InitOpcodes(); void InitOpcodes();
int Eval(std::string &str, SymbolType sym = Sym_None); int Eval(std::string &str, SymbolType sym = Sym_None);
CExpr EvalE(std::string &str, SymbolType sym = Sym_None);
CExpr EvalRpn(rpn *r, SymbolType sym); CExpr EvalRpn(rpn *r, SymbolType sym);
OpToken OperToken(char c); OpToken OperToken(char c);
char OperChar(OpToken c); char OperChar(OpToken c);
bool IsSymbol(std::string &str); void WriteCell(FILE *fp, ucell *c, int repeat);
private: private:
std::vector<Asm *> CodeList; std::vector<Asm *> CodeList;
std::map<std::string,int> OpCodes; std::map<std::string,int> OpCodes;
@ -96,6 +100,9 @@ private:
int cellsize; int cellsize;
int stacksize; int stacksize;
bool debug; bool debug;
bool pack;
bool dopt;
int bitsOut;
Asm *curAsm; Asm *curAsm;
}; };

View File

@ -45,6 +45,7 @@ DataMngr::Datum::Datum()
db = false; db = false;
offset = -1; offset = -1;
fill = 0; fill = 0;
zeroed = false;
} }
void DataMngr::Add(std::string &s, CExpr &expr, bool db, int fill) void DataMngr::Add(std::string &s, CExpr &expr, bool db, int fill)
@ -128,3 +129,68 @@ void DataMngr::GetData(std::vector<DataMngr::Datum *> &dList)
} }
} }
void DataMngr::PrintTable()
{
std::vector<DataMngr::Datum *>::iterator i;
DataMngr::Datum *p = 0;
printf("Symbol\tSize\n");
for (i=List.begin(); i!=List.end(); i++)
{
p = (*i);
printf("%s\t%d\n", p->symbol.c_str(), p->offset);
}
}
//Rewrite the DAT section so empties are at the end
void DataMngr::Optimize()
{
std::vector<DataMngr::Datum *> DbList;
std::vector<DataMngr::Datum *> MtList;
std::vector<DataMngr::Datum *>::iterator i;
for (i=List.begin(); i!=List.end(); i++)
{
if ( (*i)->db )
{
DbList.push_back( (*i) );
} else if ( (*i)->fill == 0 ) {
MtList.push_back( (*i) );
} else {
DbList.push_back( (*i) );
}
}
List.clear();
lastOffset = 0;
cursize = 0;
int size = 0;
for (i=DbList.begin(); i!=DbList.end(); i++)
{
size = (( (*i)->e.GetType() == Val_Number
|| (*i)->e.GetType() == Val_Float ) ?
cellsize : (*i)->e.Size() * cellsize);
(*i)->offset = lastOffset;
lastOffset += size;
(*i)->zeroed = false;
List.push_back( (*i) );
}
cursize = lastOffset;
DbList.clear();
for (i=MtList.begin(); i!=MtList.end(); i++)
{
size = ( (*i)->e.GetNumber() * cellsize );
(*i)->offset = lastOffset;
lastOffset += size;
(*i)->zeroed = true;
List.push_back( (*i) );
}
MtList.clear();
optimized = true;
}

View File

@ -35,22 +35,27 @@ public:
bool db; bool db;
int offset; int offset;
int fill; int fill;
bool zeroed;
}; };
public: public:
~DataMngr(); ~DataMngr();
DataMngr() { cellsize = 4; lastOffset = 0; cursize = 0; } DataMngr() { cellsize = 4; lastOffset = 0; cursize = 0; optimized = false; }
DataMngr(int cell) { lastOffset = 0; cellsize = cell; cursize = 0; } DataMngr(int cell) { lastOffset = 0; cellsize = cell; cursize = 0; optimized = false; }
void Add(std::string &s, CExpr &expr, bool db = false, int fill = 0); void Add(std::string &s, CExpr &expr, bool db = false, int fill = 0);
DataMngr::Datum *FindData(std::string &sym); DataMngr::Datum *FindData(std::string &sym);
void GetData(std::vector<DataMngr::Datum *> &dList); void GetData(std::vector<DataMngr::Datum *> &dList);
int GetOffset(std::string &sym); int GetOffset(std::string &sym);
int GetSize(); int GetSize();
void Clear(); void Clear();
void PrintTable();
void Optimize();
bool IsOptimized() { return optimized; }
private: private:
std::vector<DataMngr::Datum *> List; std::vector<DataMngr::Datum *> List;
int lastOffset; int lastOffset;
int cellsize; int cellsize;
int cursize; int cursize;
bool optimized;
public: public:
static const int nof = -1; static const int nof = -1;
}; };

View File

@ -24,11 +24,10 @@
std::string filename; std::string filename;
std::string output_name; std::string output_name;
Compiler Program;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Compiler Program;
get_options(argc, argv, Program); get_options(argc, argv, Program);
if (filename.size() < 1) if (filename.size() < 1)
@ -76,6 +75,12 @@ void get_options(int argc, char **argv, Compiler &Prog)
} }
break; break;
} }
case 'c':
{
Program.SetPack();
opt_flag = 0;
break;
}
case 'v': case 'v':
{ {
opt_flag = 0; /* no options expected */ opt_flag = 0; /* no options expected */
@ -89,6 +94,18 @@ void get_options(int argc, char **argv, Compiler &Prog)
Prog.SetDebug(); Prog.SetDebug();
break; break;
} }
case 'h':
{
opt_flag = 0;
Prog.SetDOpt();
break;
}
case 'f':
{
opt_flag = 0;
Prog.SetDOpt();
Prog.SetPack();
}
} /* switch */ } /* switch */
} else { /* - */ } else { /* - */
if (!opt_flag) if (!opt_flag)
@ -110,7 +127,7 @@ void get_options(int argc, char **argv, Compiler &Prog)
void print_version() void print_version()
{ {
printf("Small/AMX Assembler 1.00\n"); printf("Small/AMX Assembler 1.01\n");
printf("(C)2004 David 'BAILOPAN' Anderson\n"); printf("(C)2004 David 'BAILOPAN' Anderson\n");
} }
@ -120,5 +137,8 @@ void print_options()
printf("\t-d\t\t- Add debug opcodes (will double file size)\n"); printf("\t-d\t\t- Add debug opcodes (will double file size)\n");
printf("\t-v\t\t- Output version and exit\n"); printf("\t-v\t\t- Output version and exit\n");
printf("\t-o\t\t- Specify file to write\n"); printf("\t-o\t\t- Specify file to write\n");
printf("\t-c\t\t- Enable compact encoding\n");
printf("\t-h\t\t- Optimize DAT section\n");
printf("\t-f\t\t- Optimal Build\n");
printf("\n"); printf("\n");
} }