cfapass.cpp
No OneTemporary

File Metadata

Created
Fri, Mar 13, 7:18 PM

cfapass.cpp

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* cfapass.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file cfapass.h
* \brief Control Flow Analysis(CFA)
*/
#include "cfapass.h"
#include "analysis/cfagraph.h"
#include "analysis/DominatorsTreeAnalysisProvider.h"
#include <boost/range/iterator_range_core.hpp>
using namespace std;
using namespace xreate::cfa;
void
CFAPassBasic::initSignatures(){
auto range = man->root->__interfacesData.equal_range(CFA);
for (auto i = range.first; i!= range.second; ++i){
__signatures.emplace(i->second.op, i->second);
}
}
void
CFAPassBasic::run(){
initSignatures();
return AbstractPass::run();
}
void
CFAPassBasic::finish(){
man->transcend->registerReport(__context.graph);
dominators::DominatorsTreeAnalysisProvider* reportDominators = new dominators::DominatorsTreeAnalysisProvider();
reportDominators->run(__context.graph);
man->transcend->registerReport(reportDominators);
return AbstractPass::finish();
}
void
CFAPassBasic::processFnCall(ManagedFnPtr function, PassContext context){
TranscendLayer* transcend = man->transcend;
__context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
return AbstractPass::processFnCall(function, context);
}
void
CFAPassBasic::processFnCallUncertain(ManagedFnPtr function, PassContext context){
TranscendLayer* transcend = man->transcend;
__context.graph->addCallConnection(transcend->pack(context.scope), function->getName());
return AbstractPass::processFnCallUncertain(function, context);
}
void
CFAPassBasic::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){
TranscendLayer* transcend = man->transcend;
const CodeScope* scopeParent = context.scope;
ScopePacked scopeId = transcend->pack(scope);
__context.graph->addScope(scope);
//Parent Relations
if (scopeParent){
__context.graph->addParentConnection(scopeId, transcend->pack(scopeParent));
} else {
__context.graph->addParentConnection(scopeId, context.function->getName());
}
//TOTEST scope annotations
//SECTIONTAG context gather scope annotations
__context.graph->addScopeAnnotations(scopeId, scope->tags);
__context.graph->addContextRules(scopeId, scope->contextRules);
return AbstractPass::process(scope, context, hintBlockDecl);
}
//TOTEST scope annotations via scheme
void
CFAPassBasic::process(const Expression& expression, PassContext context, const std::string& varDecl){
TranscendLayer* transcend = man->transcend;
if (expression.__state == Expression::COMPOUND){
Operator op= expression.op;
if (__signatures.count(op)) {
assert(expression.blocks.size());
for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) {
__context.graph->addScopeAnnotations(transcend->pack(expression.blocks.front()), scheme.second.getOperands());
}
}
}
return AbstractPass::process(expression, context, varDecl);
}
void
CFAPassBasic::process(ManagedFnPtr function){
__context.graph->addFunctionAnnotations(function->getName(), function->getTags());
return AbstractPass::process(function);
}
CFAPassBasic::CFAPassBasic(PassManager* manager)
: AbstractPass(manager)
, __context{new CFAGraph(manager->transcend)}
{}
/****************************SCOPE DEPENDENCIES********************************/
void
CFAPassDependenciesDecorator::process(const Expression& expression, PassContext context, const std::string& varDecl){
TranscendLayer* transcend = man->transcend;
if (expression.__state == Expression::COMPOUND)
switch(expression.op){
case Operator::SEQUENCE:{
ScopePacked scopePrev = transcend->pack(expression.blocks.front());
for(auto scopeIt= ++expression.blocks.begin(); scopeIt != expression.blocks.end(); ++scopeIt){
ScopePacked scopeCurrent = transcend->pack(*scopeIt);
__context.graph->addDependency(scopeCurrent, scopePrev);
scopePrev = scopeCurrent;
}
break;
}
default: break;
}
return Parent::process(expression, context, varDecl);
}
void
CFAPassDependenciesDecorator::processFnCall(ManagedFnPtr function, PassContext context){
TranscendLayer* transcend = man->transcend;
const CodeScope* scopeCaller = context.scope;
assert(scopeCaller);
ScopePacked scopeCallerPacked = transcend->pack(scopeCaller);
if(__context.graph->isDependent(scopeCallerPacked)){
ScopePacked scopeCalleePacked = transcend->pack(function->getEntryScope());
__context.graph->transmitDependencies(scopeCalleePacked, scopeCallerPacked);
}
Parent::processFnCall(function, context);
}
void
CFAPassDependenciesDecorator::processFnCallUncertain(ManagedFnPtr function, PassContext context){
TranscendLayer* transcend = man->transcend;
const CodeScope* scopeCaller = context.scope;
assert(scopeCaller);
ScopePacked scopeCallerPacked = transcend->pack(scopeCaller);
if(__context.graph->isDependent(scopeCallerPacked)){
ScopePacked scopeCalleePacked = transcend->pack(function->getEntryScope());
__context.graph->transmitDependencies(scopeCalleePacked, scopeCallerPacked);
}
Parent::processFnCallUncertain(function, context);
}
void
CFAPassDependenciesDecorator::process(CodeScope* scope,
PassContext context, const std::string& hintBlockDecl){
TranscendLayer* transcend = man->transcend;
const CodeScope* scopeParent = context.scope;
if (scopeParent){
ScopePacked scopePacked = transcend->pack(scope);
ScopePacked scopeParentPacked = transcend->pack(scopeParent);
if (!__context.graph->isDependent(scopePacked) &&
__context.graph->isDependent(scopeParentPacked)) {
__context.graph->transmitDependencies(scopePacked, scopeParentPacked);
}
}
Parent::process(scope, context, hintBlockDecl);
}
/**
* \class xreate::cfa::CFAPass
* \details Provides CFA, important analysis for reasoning. Iterates over AST and stores collected data in CFAGraph
*/

Event Timeline