| //===-- 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; |
| } |