143 lines
2.7 KiB
C++
143 lines
2.7 KiB
C++
|
|
#include "nodes.hpp"
|
|
#include "std.hpp"
|
|
|
|
//////////////////
|
|
// The program! //
|
|
//////////////////
|
|
Environ* ProgNode::semant(Environ* e)
|
|
{
|
|
file_lab = genLabel();
|
|
|
|
StmtSeqNode::reset(stmts->file, file_lab);
|
|
|
|
a_ptr<Environ> env(new Environ(genLabel(), Type::int_type, 0, e));
|
|
|
|
consts->proto(env->decls, env);
|
|
structs->proto(env->typeDecls, env);
|
|
structs->semant(env);
|
|
funcs->proto(env->funcDecls, env);
|
|
stmts->semant(env);
|
|
funcs->semant(env);
|
|
datas->proto(env->decls, env);
|
|
datas->semant(env);
|
|
|
|
sem_env = env.release();
|
|
return sem_env;
|
|
}
|
|
|
|
void ProgNode::translate(Codegen* g, const vector<UserFunc>& usrfuncs)
|
|
{
|
|
int k;
|
|
|
|
if (g->debug)
|
|
g->s_data(stmts->file, file_lab);
|
|
|
|
//enumerate locals
|
|
int size = enumVars(sem_env);
|
|
|
|
//'Main' label
|
|
g->enter("__MAIN", size);
|
|
|
|
//reset data pointer
|
|
g->code(call("__bbRestore", global("__DATA")));
|
|
|
|
//load external libs
|
|
g->code(call("__bbLoadLibs", global("__LIBS")));
|
|
|
|
//call main program
|
|
g->code(jsr(sem_env->funcLabel + "_begin"));
|
|
g->code(jump(sem_env->funcLabel + "_leave"));
|
|
g->label(sem_env->funcLabel + "_begin");
|
|
|
|
//create locals
|
|
TNode* t = createVars(sem_env);
|
|
if (t)
|
|
g->code(t);
|
|
if (g->debug) {
|
|
string t = genLabel();
|
|
g->s_data("<main program>", t);
|
|
g->code(call("__bbDebugEnter", local(0), iconst((int)sem_env), global(t)));
|
|
}
|
|
|
|
//no user funcs used!
|
|
usedfuncs.clear();
|
|
|
|
//program statements
|
|
stmts->translate(g);
|
|
|
|
//emit return
|
|
g->code(ret());
|
|
|
|
//check labels
|
|
for (k = 0; k < sem_env->labels.size(); ++k) {
|
|
if (sem_env->labels[k]->def < 0)
|
|
ex("Undefined label '" + sem_env->labels[k]->name + "'", sem_env->labels[k]->ref, stmts->file);
|
|
}
|
|
|
|
//leave main program
|
|
g->label(sem_env->funcLabel + "_leave");
|
|
t = deleteVars(sem_env);
|
|
if (g->debug)
|
|
t = new TNode(IR_SEQ, call("__bbDebugLeave"), t);
|
|
g->leave(t, 0);
|
|
|
|
//structs
|
|
structs->translate(g);
|
|
|
|
//non-main functions
|
|
funcs->translate(g);
|
|
|
|
//data
|
|
datas->translate(g);
|
|
|
|
//library functions
|
|
map<string, vector<int>> libFuncs;
|
|
|
|
//lib ptrs
|
|
g->flush();
|
|
g->align_data(4);
|
|
for (k = 0; k < usrfuncs.size(); ++k) {
|
|
const UserFunc& fn = usrfuncs[k];
|
|
|
|
if (!usedfuncs.count(fn.ident))
|
|
continue;
|
|
|
|
libFuncs[fn.lib].push_back(k);
|
|
|
|
g->i_data(0, "_f" + fn.ident);
|
|
}
|
|
|
|
//LIBS chunk
|
|
g->flush();
|
|
g->label("__LIBS");
|
|
map<string, vector<int>>::const_iterator lf_it;
|
|
for (lf_it = libFuncs.begin(); lf_it != libFuncs.end(); ++lf_it) {
|
|
//lib name
|
|
g->s_data(lf_it->first);
|
|
|
|
const vector<int>& fns = lf_it->second;
|
|
|
|
for (int j = 0; j < fns.size(); ++j) {
|
|
const UserFunc& fn = usrfuncs[fns[j]];
|
|
|
|
//proc name
|
|
g->s_data(fn.proc);
|
|
|
|
g->p_data("_f" + fn.ident);
|
|
}
|
|
g->s_data("");
|
|
}
|
|
g->s_data("");
|
|
|
|
//DATA chunk
|
|
g->flush();
|
|
g->align_data(4);
|
|
g->label("__DATA");
|
|
datas->transdata(g);
|
|
g->i_data(0);
|
|
|
|
//Thats IT!
|
|
g->flush();
|
|
}
|