dfapass.cpp
No OneTemporary

File Metadata

Created
Fri, Mar 13, 2:20 AM

dfapass.cpp

#include "pass/dfapass.h"
#include "analysis/dfagraph.h"
#include "passmanager.h"
#include "clasplayer.h"
#include <boost/format.hpp>
using namespace std;
using namespace xreate::analysis;
namespace xreate{
DFAPass::DFAPass(PassManager* manager)
: AbstractPass(manager)
, __context{new xreate::analysis::DFAGraph(manager->clasp)}
, clasp(manager->clasp)
{}
SymbolNode
DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
const SymbolNode& retActual = AbstractPass::process(scope, context, hintBlockDecl);
const SymbolPacked& retFormal{0, clasp->pack(scope)};
__context.graph->addConnection(retFormal, retActual, DFGConnection::STRONG);
return retFormal;
}
SymbolNode
DFAPass::process(const Expression& expression, PassContext context, const std::string& decl)
{
ExpressionCache cache;
if (!decl.empty()){
cache.result = clasp->pack(context.scope->findSymbol(decl), context.function->getName() + ":" + decl);
} else if (!expression.tags.empty()) {
cache.result = __context.graph->createAnonymousSymbol(clasp->pack(context.scope));
} else {
cache.result = SymbolTransient{{}, clasp->pack(context.scope)};
}
cache.operands.reserve(expression.getOperands().size());
for (const Expression &op: expression.getOperands()) {
cache.operands.push_back(process(op, context));
}
cache.blocks.reserve(expression.blocks.size());
for (CodeScope* scope: expression.blocks) {
cache.blocks.push_back(process(scope, context));
}
if (expression.__state == Expression::COMPOUND) {
processCompoundOp(expression, context, cache, decl);
} else {
processElementaryOp(expression, context, cache, decl);
}
applyDependencies(expression, context, cache, decl);
applyStaticAnnotations(expression, context, cache, decl);
applySignatureAnnotations(expression, context, cache, decl);
applyInPlaceAnnotations(expression, context, cache, decl);
//TODO Null ad hoc DFG implementation
// if (expression.isNone()){
// return SymbolTransient{{Atom<Identifier_t>(Config::get("clasp.nonevalue"))}};
// }
//non initialized(SymbolInvalid) value
return cache.result;
}
void
DFAPass::processElementaryOp(const Expression& expression, PassContext context, DFAPass::ExpressionCache& cache, const std::string& varDecl){
switch(expression.__state) {
case Expression::IDENT: {
std::string identifier = expression.getValueString();
SymbolNode nodeFrom = AbstractPass::process(expression, context, identifier);
if (SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result)){
__context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::STRONG);
} else {
// cache.result = nodeFrom;
}
break;
}
default: break;
}
}
void
DFAPass::processCompoundOp(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& varDecl){
switch(expression.op) {
//apply calling relation
case Operator::CALL: {
const string &nameCalleeFunction = expression.getValueString();
//TODO implement processFnCall/Uncertain
list<ManagedFnPtr> variantsCalleeFunction = man->root->getFunctionVariants(nameCalleeFunction);
if (variantsCalleeFunction.size()!=1) return;
ManagedFnPtr function= variantsCalleeFunction.front();
// set calling relations:
CodeScope *scopeRemote = function->getEntryScope();
std::vector<SymbolNode>::iterator nodeActual = cache.operands.begin();
for (const std::string &identFormal: scopeRemote->__bindings) {
const Symbol &symbolFormal = scopeRemote->findSymbol(identFormal);
__context.graph->addConnection(clasp->pack(symbolFormal, nameCalleeFunction + ":" + identFormal), *nodeActual, DFGConnection::WEAK);
++nodeActual;
}
//TODO represent RET connection
break;
}
//apply PROTOTYPE relation
case Operator::MAP: {
SymbolNode nodeFrom= cache.operands.front();
SymbolPacked* nodeFromPacked = boost::get<SymbolPacked>(&nodeFrom);
assert(nodeFromPacked);
SymbolPacked* nodeTo = boost::get<SymbolPacked>(&cache.result);
assert(nodeTo);
__context.graph->addConnection(*nodeTo, *nodeFromPacked, DFGConnection::PROTOTYPE);
break;
}
default: break;
}
}
void
DFAPass::applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
for (SymbolNode &op: cache.operands) {
__context.graph->addDependencyConnection(cache.result, op);
}
for (SymbolNode &block: cache.blocks) {
__context.graph->addDependencyConnection(cache.result, block);
}
switch(expression.__state) {
case Expression::IDENT: {
const string& identName = expression.getValueString();
SymbolNode identSymbol = clasp->pack(context.scope->findSymbol(identName), context.function->getName() + ":" + identName);
__context.graph->addDependencyConnection(cache.result, identSymbol);
}
default: break;
}
}
void
DFAPass::applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
switch(expression.__state) {
case Expression::NUMBER:
case Expression::STRING:
__context.graph->addAnnotation(cache.result, Expression(Atom<Identifier_t>("static")));
break;
default: break;
}
}
void
DFAPass::applySignatureAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
if (__signatures.count(expression.op)) {
const Expression &scheme = __signatures.at(expression.op);
//TODO add possibility to specifi signature for a particular function
// if (expression.op == Operator::CALL || expression.op == Operator::INDEX){
// string caption = expression.getValueString();
// operands.push_back(process(Expression(move(caption)), context, ""));
// }
std::vector<SymbolNode>::iterator arg = cache.operands.begin();
std::vector<Expression>::const_iterator tag = ++scheme.getOperands().begin();
while (tag != scheme.getOperands().end()) {
if (tag->__state != Expression::INVALID) {
__context.graph->addAnnotation(*arg, Expression(*tag));
}
++arg; ++tag;
}
//TODO represent RET connection
// Expression retTag = *scheme.getOperands().begin();
// if (retTag.__state != Expression::INVALID) {
// __context.graph->addAnnotation(node, move(retTag));
// }
}
}
void
DFAPass::applyInPlaceAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){
// write down in-place expression tags:
for (pair<std::string, Expression> tag: expression.tags) {
__context.graph->addAnnotation(cache.result, Expression(tag.second));
}
}
void
DFAPass::run()
{
init();
return AbstractPass::run();
}
void
DFAPass::init()
{
for (const Expression& scheme: man->root->__dfadata)
{
__signatures.emplace(scheme.op, scheme);
}
}
void DFAPass::finish()
{
man->clasp->setDFAData(move(__context.graph));
}
template<>
SymbolNode defaultValue(){return SymbolInvalid();};
}

Event Timeline