blob: 720df6a11437fd960f7c94ce428992cc6616ad7c [file] [log] [blame]
//===-- Pass Interface Class ------------------------------------*- C++ -*-===//
//
// High Level Virtual Machine (HLVM)
//
// Copyright (C) 2006 Reid Spencer. All Rights Reserved.
//
// This software is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
// This software is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library in the file named LICENSE.txt; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301 USA
//
//===----------------------------------------------------------------------===//
/// @file hlvm/Pass/Pass.cpp
/// @author Reid Spencer <rspencer@reidspencer.org> (original author)
/// @date 2006/05/18
/// @since 0.1.0
/// @brief Implements the functions of class hlvm::Pass::Pass.
//===----------------------------------------------------------------------===//
#include <hlvm/Pass/Pass.h>
#include <hlvm/AST/AST.h>
#include <hlvm/AST/Bundle.h>
#include <hlvm/AST/ContainerType.h>
#include <hlvm/AST/Linkables.h>
#include <hlvm/Base/Assert.h>
using namespace hlvm;
using namespace llvm;
namespace {
class PassManagerImpl : public PassManager
{
public:
PassManagerImpl() : PassManager(), pre(), post() {}
void addPass(Pass* p);
virtual void runOn(AST* tree);
virtual void runOnNode(Node* startAt);
inline void runIfInterested(Pass* p, Node* n, Pass::TraversalKinds m);
inline void runPreOrder(Node* n);
inline void runPostOrder(Node* n);
template<class NodeClass>
inline void runOn(NodeClass* b);
private:
std::vector<Pass*> pre;
std::vector<Pass*> post;
std::vector<Pass*> all;
};
void
PassManagerImpl::addPass(Pass* p)
{
all.push_back(p);
if (p->mode() & Pass::PreOrderTraversal)
pre.push_back(p);
if (p->mode() & Pass::PostOrderTraversal)
post.push_back(p);
}
inline void
PassManagerImpl::runIfInterested(Pass* p, Node* n, Pass::TraversalKinds m)
{
int interest = p->interest();
if (interest == 0 ||
((interest & Pass::Type_Interest) && n->isType()) ||
((interest & Pass::Function_Interest) && n->isFunction()) ||
((interest & Pass::Block_Interest) && n->is(BlockID)) ||
((interest & Pass::Operator_Interest) && n->isOperator()) ||
((interest & Pass::Program_Interest) && n->is(ProgramID)) ||
((interest & Pass::Variable_Interest) && n->is(VariableID))
) {
p->handle(n,m);
}
}
inline void
PassManagerImpl::runPreOrder(Node* n)
{
std::vector<Pass*>::iterator I = pre.begin(), E = pre.end();
while (I != E) {
runIfInterested(*I,n,Pass::PreOrderTraversal);
++I;
}
}
inline void
PassManagerImpl::runPostOrder(Node* n)
{
std::vector<Pass*>::iterator I = post.begin(), E = post.end();
while (I != E) {
runIfInterested(*I,n,Pass::PostOrderTraversal);
++I;
}
}
template<> inline void
PassManagerImpl::runOn(ConstantValue* cst)
{
hlvmAssert(cst && "Null constant?");
hlvmAssert(isa<Constant>(cst));
runPreOrder(cst);
// FIXME: Eventually we'll have structured constants which need to have
// their contents examined as well.
runPostOrder(cst);
}
template<> inline void
PassManagerImpl::runOn(Operator* op)
{
hlvmAssert(op && "Null operator?");
runPreOrder(op);
size_t limit = op->getNumOperands();
for (size_t i = 0; i < limit; ++i)
runOn(op->getOperand(i));
runPostOrder(op);
}
template<> inline void
PassManagerImpl::runOn(Block* b)
{
hlvmAssert(b && "Null block?");
runPreOrder(b);
for (Block::iterator I = b->begin(), E = b->end(); I != E; ++I)
runOn(cast<Operator>(*I)); // recurse, possibly!
runPostOrder(b);
}
template<> inline void
PassManagerImpl::runOn(Linkable* l)
{
runPreOrder(l);
if (Function* F = dyn_cast<Function>(l))
if (Block* B = F->getBlock())
runOn(B);
runPostOrder(l);
}
template<> inline void
PassManagerImpl::runOn(Type* Ty)
{
runPreOrder(Ty);
runPostOrder(Ty);
}
template<> inline void
PassManagerImpl::runOn(Bundle* b)
{
hlvmAssert(b && "Null bundle?");
runPreOrder(b);
for (Bundle::tlist_iterator TI = b->tlist_begin(), TE = b->tlist_end();
TI != TE; ++TI)
runOn(const_cast<Type*>(*TI));
for (Bundle::clist_iterator CI = b->clist_begin(), CE = b->clist_end();
CI != CE; ++CI) {
runPreOrder(const_cast<Constant*>(*CI));
if (Function* F = dyn_cast<Function>(*CI))
if (Block* B = F->getBlock())
runOn(B);
runPostOrder(const_cast<Constant*>(*CI));
}
runPostOrder(b);
}
void PassManagerImpl::runOn(AST* tree)
{
hlvmAssert(tree && "Null tree?");
// Call the initializers
std::vector<Pass*>::iterator PI = all.begin(), PE = all.end();
while (PI != PE) { (*PI)->handleInitialize(tree); ++PI; }
// Just a little optimization for empty pass managers
if (pre.empty() && post.empty())
return;
// Traverse each of the bundles in the AST node.
for (AST::iterator I = tree->begin(), E = tree->end(); I != E; ++I)
runOn(*I);
// Call the terminators
PI = all.begin(), PE = all.end();
while (PI != PE) { (*PI)->handleTerminate(); ++PI; }
}
void
PassManagerImpl::runOnNode(Node* startAt)
{
// Check to make sure startAt is in tree
hlvmAssert(startAt != 0 && "Can't run passes from null start");
if (isa<AST>(startAt))
runOn(cast<AST>(startAt));
else if (isa<Bundle>(startAt))
runOn(cast<Bundle>(startAt));
else if (isa<Block>(startAt))
runOn(cast<Block>(startAt));
else if (isa<Linkable>(startAt))
runOn(cast<Linkable>(startAt));
else if (isa<ConstantValue>(startAt))
runOn(cast<ConstantValue>(startAt));
else if (isa<Operator>(startAt))
runOn(cast<Operator>(startAt));
else if (isa<Type>(startAt))
runOn(cast<Type>(startAt));
else
hlvmAssert(!"startAt type not supported");
}
} // anonymous namespace
Pass::~Pass()
{
}
void
Pass::handleInitialize(AST* tree)
{
}
void
Pass::handleTerminate()
{
}
PassManager::~PassManager()
{
}
PassManager*
PassManager::create()
{
return new PassManagerImpl;
}