/* Theoretic - Graph Theoretic Byte Code Engineering * Copyright (C) 2001-2002 Jay Freeman (saurik) */ /* * Redistribution and use in source and binary * forms, with or without modification, are permitted * provided that the following conditions are met: * * 1. Redistributions of source code must retain the * above copyright notice, this list of conditions * and the following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions * and the following disclaimer in the documentation * and/or other materials provided with the * distribution. * 3. The name of the author may not be used to endorse * or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "stdafx.h" #include "theoretic/OpGraph.h" #include "engines/msil.h" namespace Theoretic { OpGraph::OpGraph(Operation *root) : root(root) { Add(root); } OpGraph::~OpGraph() { for (OperSet::iterator op = ops.begin(); op != ops.end(); ++op) delete *op; } void OpGraph::Collect() { OperSet old = ops; ops.clear(); Add(root); OperSet remove; std::set_difference(old.begin(), old.end(), ops.begin(), ops.end(), std::inserter(remove, remove.begin())); for (OperSet::iterator op = remove.begin(); op != remove.end(); ++op) delete *op; } Operation *OpGraph::GetRoot() { return root; } void OpGraph::Add(Operation *op) { if (op != NULL && ops.insert(op).second) { const Operation::LinkMap &links = op->GetLinks(); for (Operation::LinkMap::const_iterator link = links.begin(); link != links.end(); ++link) Add(link->second); } } void OpGraph::Add(const OpList &list) { const OpList::OperList &ops = list.GetOps(); for (OpList::OperList::const_iterator op = ops.begin(); op != ops.end(); ++op) Add(*op); } void OpGraph::Graft(Operation *from, Operation *to) { if (root == from) root = to; for (OperSet::iterator op = ops.begin(); op != ops.end(); ++op) { Operation::LinkMap &links = (*op)->GetLinks(); for (Operation::LinkMap::iterator link = links.begin(); link != links.end(); ++link) { OpList::OperList &list = link->second.GetOps(); for (OpList::OperList::iterator target = list.begin(); target != list.end(); ++target) if (*target == from) *target = to; } } } void OpGraph::Cement(const Metallurgy::Method &method) { for (OperSet::iterator op = ops.begin(); op != ops.end(); ++op) (*op)->Cement(method); } void OpGraph::Optimize() { start: Collect(); {for (OperSet::const_iterator iop = ops.begin(); iop != ops.end(); ++iop) { Operation *op = *iop; if (op->Resolvable() && !op->ResolveStack(this, NULL)) goto start; }}// Collect(); {for (OperSet::const_iterator iop = ops.begin(); iop != ops.end(); ++iop) { Operation *op = *iop; if (op->GetName() != L"msil:brtrue") continue; }}// } OpGraph::LinkList OpGraph::BackLinks(Operation *from) const { LinkList back; for (OperSet::const_iterator op = ops.begin(); op != ops.end(); ++op) { const Operation::LinkMap &links = (*op)->GetLinks(); for (Operation::LinkMap::const_iterator link = links.begin(); link != links.end(); ++link) { const OpList::OperList &list = link->second.GetOps(); for (int target(0); target < list.size(); ++target) if (list[target] == from) back.push_back(Link(*op, LinkRef(link->first, target))); } } return back; } const OperSet &OpGraph::GetOps() const { return ops; } }