Files
BlitzNext/compiler/lib/prognode.cpp
T

169 lines
3.6 KiB
C++
Raw Normal View History

2019-01-19 18:28:07 +01:00
#include "prognode.hpp"
#include <map>
#include "codegen.hpp"
#include "declnode.hpp"
#include "environ.hpp"
#include "label.hpp"
#include "stmtnode.hpp"
#include <stdutil.hpp>
ProgNode::ProgNode(std::shared_ptr<DeclSeqNode> constants, std::shared_ptr<DeclSeqNode> structures,
std::shared_ptr<DeclSeqNode> functions, std::shared_ptr<DeclSeqNode> datas,
std::shared_ptr<StmtSeqNode> statements)
: consts(constants), structs(structures), funcs(functions), datas(datas), stmts(statements)
{}
ProgNode::~ProgNode()
{
this->consts.reset();
this->structs.reset();
this->funcs.reset();
this->datas.reset();
this->stmts.reset();
}
2014-01-31 08:23:00 +13:00
//////////////////
// The program! //
//////////////////
2019-01-19 18:28:07 +01:00
std::shared_ptr<Environ> ProgNode::semant(Environ* e)
2019-01-18 17:04:57 +01:00
{
file_lab = genLabel();
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
StmtSeqNode::reset(stmts->file, file_lab);
2014-01-31 08:23:00 +13:00
2019-01-19 18:28:07 +01:00
std::shared_ptr<Environ> env = std::make_shared<Environ>(genLabel(), Type::int_type, 0, 0);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
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);
2014-01-31 08:23:00 +13:00
2019-01-19 18:28:07 +01:00
sem_env = env;
return env;
2014-01-31 08:23:00 +13:00
}
2019-01-19 18:28:07 +01:00
void ProgNode::translate(Codegen* g, const std::vector<UserFunc>& usrfuncs)
2019-01-18 17:04:57 +01:00
{
2014-01-31 08:23:00 +13:00
int k;
2019-01-18 17:04:57 +01:00
if (g->debug)
g->s_data(stmts->file, file_lab);
2014-01-31 08:23:00 +13:00
//enumerate locals
2019-01-18 17:04:57 +01:00
int size = enumVars(sem_env);
2014-01-31 08:23:00 +13:00
//'Main' label
2019-01-18 17:04:57 +01:00
g->enter("__MAIN", size);
2014-01-31 08:23:00 +13:00
//reset data pointer
2019-01-18 17:04:57 +01:00
g->code(call("__bbRestore", global("__DATA")));
2014-01-31 08:23:00 +13:00
//load external libs
2019-01-18 17:04:57 +01:00
g->code(call("__bbLoadLibs", global("__LIBS")));
2014-01-31 08:23:00 +13:00
//call main program
2019-01-18 17:04:57 +01:00
g->code(jsr(sem_env->funcLabel + "_begin"));
g->code(jump(sem_env->funcLabel + "_leave"));
g->label(sem_env->funcLabel + "_begin");
2014-01-31 08:23:00 +13:00
//create locals
2019-01-18 17:04:57 +01:00
TNode* t = createVars(sem_env);
if (t)
g->code(t);
if (g->debug) {
2019-01-19 18:28:07 +01:00
std::string t = genLabel();
2019-01-18 17:04:57 +01:00
g->s_data("<main program>", t);
g->code(call("__bbDebugEnter", local(0), iconst((int)sem_env), global(t)));
2014-01-31 08:23:00 +13:00
}
//no user funcs used!
usedfuncs.clear();
//program statements
2019-01-18 17:04:57 +01:00
stmts->translate(g);
2014-01-31 08:23:00 +13:00
//emit return
2019-01-18 17:04:57 +01:00
g->code(ret());
2014-01-31 08:23:00 +13:00
//check labels
2019-01-18 17:04:57 +01:00
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);
2014-01-31 08:23:00 +13:00
}
//leave main program
2019-01-18 17:04:57 +01:00
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);
2014-01-31 08:23:00 +13:00
//structs
2019-01-18 17:04:57 +01:00
structs->translate(g);
2014-01-31 08:23:00 +13:00
//non-main functions
2019-01-18 17:04:57 +01:00
funcs->translate(g);
2014-01-31 08:23:00 +13:00
//data
2019-01-18 17:04:57 +01:00
datas->translate(g);
2014-01-31 08:23:00 +13:00
//library functions
2019-01-19 18:28:07 +01:00
std::map<std::string, std::vector<int>> libFuncs;
2014-01-31 08:23:00 +13:00
//lib ptrs
g->flush();
g->align_data(4);
2019-01-18 17:04:57 +01:00
for (k = 0; k < usrfuncs.size(); ++k) {
const UserFunc& fn = usrfuncs[k];
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
if (!usedfuncs.count(fn.ident))
continue;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
libFuncs[fn.lib].push_back(k);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
g->i_data(0, "_f" + fn.ident);
2014-01-31 08:23:00 +13:00
}
//LIBS chunk
g->flush();
2019-01-18 17:04:57 +01:00
g->label("__LIBS");
2019-01-19 18:28:07 +01:00
std::map<std::string, std::vector<int>>::const_iterator lf_it;
2019-01-18 17:04:57 +01:00
for (lf_it = libFuncs.begin(); lf_it != libFuncs.end(); ++lf_it) {
2014-01-31 08:23:00 +13:00
//lib name
2019-01-18 17:04:57 +01:00
g->s_data(lf_it->first);
2014-01-31 08:23:00 +13:00
2019-01-19 18:28:07 +01:00
const std::vector<int>& fns = lf_it->second;
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
for (int j = 0; j < fns.size(); ++j) {
const UserFunc& fn = usrfuncs[fns[j]];
2014-01-31 08:23:00 +13:00
//proc name
2019-01-18 17:04:57 +01:00
g->s_data(fn.proc);
2014-01-31 08:23:00 +13:00
2019-01-18 17:04:57 +01:00
g->p_data("_f" + fn.ident);
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:57 +01:00
g->s_data("");
2014-01-31 08:23:00 +13:00
}
2019-01-18 17:04:57 +01:00
g->s_data("");
2014-01-31 08:23:00 +13:00
//DATA chunk
g->flush();
2019-01-18 17:04:57 +01:00
g->align_data(4);
g->label("__DATA");
datas->transdata(g);
2014-01-31 08:23:00 +13:00
g->i_data(0);
//Thats IT!
g->flush();
}
2019-01-19 18:28:07 +01:00
UserFunc::UserFunc(const UserFunc& t) : ident(t.ident), proc(t.proc), lib(t.lib) {}
UserFunc::UserFunc(const std::string& id, const std::string& pr, const std::string& lb) : ident(id), proc(pr), lib(lb)
{}