From 7df0fd90f597b6c55ec60c62baba4cd5fe6acda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 12 Dec 2011 15:30:24 +0000 Subject: [PATCH] Changes by Tiago --- packages/CLPBN/clpbn/bp/BPNodeInfo.cpp | 149 - packages/CLPBN/clpbn/bp/BPNodeInfo.h | 82 - packages/CLPBN/clpbn/bp/BPSolver.cpp | 905 ---- packages/CLPBN/clpbn/bp/BPSolver.h | 192 - packages/CLPBN/clpbn/bp/BpNetwork.cpp | 811 --- packages/CLPBN/clpbn/bp/BpNetwork.h | 66 - packages/CLPBN/clpbn/bp/BpNode.cpp | 250 - packages/CLPBN/clpbn/bp/BpNode.h | 99 - packages/CLPBN/clpbn/bp/CountingBP.cpp | 198 - packages/CLPBN/clpbn/bp/CountingBP.h | 45 - packages/CLPBN/clpbn/bp/Distribution.cpp | 40 - packages/CLPBN/clpbn/bp/FgVarNode.h | 43 - packages/CLPBN/clpbn/bp/LiftedFG.cpp | 278 - packages/CLPBN/clpbn/bp/LiftedFG.h | 152 - packages/CLPBN/clpbn/bp/SPSolver.cpp | 470 -- packages/CLPBN/clpbn/bp/SPSolver.h | 130 - packages/CLPBN/clpbn/bp/Variable.h | 172 - packages/CLPBN/clpbn/bp/callgrind.h | 147 - .../CLPBN/clpbn/bp/examples/cbp_example.uai | 14 + packages/CLPBN/clpbn/bp/examples/loop.yap | 53 - .../bp/examples/town/run_town_bp_compress.sh | 60 + .../bp/examples/town/run_town_bp_convert.sh | 51 + .../bp/examples/town/run_town_bp_normal.sh | 50 + .../bp/examples/town/run_town_gibbs_tests.sh | 51 + .../bp/examples/town/run_town_jt_tests.sh | 51 + .../bp/examples/town/run_town_ve_tests.sh | 51 + .../CLPBN/clpbn/bp/examples/town/schema.yap | 65 + .../CLPBN/clpbn/bp/examples/town/tables.yap | 46 + .../clpbn/bp/examples/town/town_generator.sh | 59 + packages/CLPBN/clpbn/bp/valgrind.h | 4536 ----------------- 30 files changed, 498 insertions(+), 8818 deletions(-) delete mode 100755 packages/CLPBN/clpbn/bp/BPNodeInfo.cpp delete mode 100755 packages/CLPBN/clpbn/bp/BPNodeInfo.h delete mode 100644 packages/CLPBN/clpbn/bp/BPSolver.cpp delete mode 100644 packages/CLPBN/clpbn/bp/BPSolver.h delete mode 100644 packages/CLPBN/clpbn/bp/BpNetwork.cpp delete mode 100644 packages/CLPBN/clpbn/bp/BpNetwork.h delete mode 100644 packages/CLPBN/clpbn/bp/BpNode.cpp delete mode 100644 packages/CLPBN/clpbn/bp/BpNode.h delete mode 100644 packages/CLPBN/clpbn/bp/CountingBP.cpp delete mode 100644 packages/CLPBN/clpbn/bp/CountingBP.h delete mode 100644 packages/CLPBN/clpbn/bp/Distribution.cpp delete mode 100644 packages/CLPBN/clpbn/bp/FgVarNode.h delete mode 100644 packages/CLPBN/clpbn/bp/LiftedFG.cpp delete mode 100644 packages/CLPBN/clpbn/bp/LiftedFG.h delete mode 100644 packages/CLPBN/clpbn/bp/SPSolver.cpp delete mode 100644 packages/CLPBN/clpbn/bp/SPSolver.h delete mode 100644 packages/CLPBN/clpbn/bp/Variable.h delete mode 100644 packages/CLPBN/clpbn/bp/callgrind.h create mode 100644 packages/CLPBN/clpbn/bp/examples/cbp_example.uai delete mode 100644 packages/CLPBN/clpbn/bp/examples/loop.yap create mode 100644 packages/CLPBN/clpbn/bp/examples/town/run_town_bp_compress.sh create mode 100644 packages/CLPBN/clpbn/bp/examples/town/run_town_bp_convert.sh create mode 100644 packages/CLPBN/clpbn/bp/examples/town/run_town_bp_normal.sh create mode 100644 packages/CLPBN/clpbn/bp/examples/town/run_town_gibbs_tests.sh create mode 100644 packages/CLPBN/clpbn/bp/examples/town/run_town_jt_tests.sh create mode 100644 packages/CLPBN/clpbn/bp/examples/town/run_town_ve_tests.sh create mode 100644 packages/CLPBN/clpbn/bp/examples/town/schema.yap create mode 100644 packages/CLPBN/clpbn/bp/examples/town/tables.yap create mode 100644 packages/CLPBN/clpbn/bp/examples/town/town_generator.sh delete mode 100644 packages/CLPBN/clpbn/bp/valgrind.h diff --git a/packages/CLPBN/clpbn/bp/BPNodeInfo.cpp b/packages/CLPBN/clpbn/bp/BPNodeInfo.cpp deleted file mode 100755 index f566bcbfb..000000000 --- a/packages/CLPBN/clpbn/bp/BPNodeInfo.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include - -#include - -#include "BPNodeInfo.h" -#include "BPSolver.h" - -BPNodeInfo::BPNodeInfo (BayesNode* node) -{ - node_ = node; - ds_ = node->getDomainSize(); - piValsCalc_ = false; - ldValsCalc_ = false; - nPiMsgsRcv_ = 0; - nLdMsgsRcv_ = 0; - piVals_.resize (ds_, 1); - ldVals_.resize (ds_, 1); - const BnNodeSet& childs = node->getChilds(); - for (unsigned i = 0; i < childs.size(); i++) { - cmsgs_.insert (make_pair (childs[i], false)); - } - const BnNodeSet& parents = node->getParents(); - for (unsigned i = 0; i < parents.size(); i++) { - pmsgs_.insert (make_pair (parents[i], false)); - } -} - - - -ParamSet -BPNodeInfo::getBeliefs (void) const -{ - double sum = 0.0; - ParamSet beliefs (ds_); - for (unsigned xi = 0; xi < ds_; xi++) { - double prod = piVals_[xi] * ldVals_[xi]; - beliefs[xi] = prod; - sum += prod; - } - assert (sum); - //normalize the beliefs - for (unsigned xi = 0; xi < ds_; xi++) { - beliefs[xi] /= sum; - } - return beliefs; -} - - - -bool -BPNodeInfo::readyToSendPiMsgTo (const BayesNode* child) const -{ - for (unsigned i = 0; i < inChildLinks_.size(); i++) { - if (inChildLinks_[i]->getSource() != child - && !inChildLinks_[i]->messageWasSended()) { - return false; - } - } - return true; -} - - - -bool -BPNodeInfo::readyToSendLambdaMsgTo (const BayesNode* parent) const -{ - for (unsigned i = 0; i < inParentLinks_.size(); i++) { - if (inParentLinks_[i]->getSource() != parent - && !inParentLinks_[i]->messageWasSended()) { - return false; - } - } - return true; -} - - - -double -BPNodeInfo::getPiValue (unsigned idx) const -{ - assert (idx >=0 && idx < ds_); - return piVals_[idx]; -} - - - -void -BPNodeInfo::setPiValue (unsigned idx, Param value) -{ - assert (idx >=0 && idx < ds_); - piVals_[idx] = value; -} - - - -double -BPNodeInfo::getLambdaValue (unsigned idx) const -{ - assert (idx >=0 && idx < ds_); - return ldVals_[idx]; -} - - - -void -BPNodeInfo::setLambdaValue (unsigned idx, Param value) -{ - assert (idx >=0 && idx < ds_); - ldVals_[idx] = value; -} - - - -double -BPNodeInfo::getBeliefChange (void) -{ - double change = 0.0; - if (oldBeliefs_.size() == 0) { - oldBeliefs_ = getBeliefs(); - change = 9999999999.0; - } else { - ParamSet currentBeliefs = getBeliefs(); - for (unsigned xi = 0; xi < ds_; xi++) { - change += abs (currentBeliefs[xi] - oldBeliefs_[xi]); - } - oldBeliefs_ = currentBeliefs; - } - return change; -} - - - -bool -BPNodeInfo::receivedBottomInfluence (void) const -{ - // if all lambda values are equal, then neither - // this node neither its descendents have evidence, - // we can use this to don't send lambda messages his parents - bool childInfluenced = false; - for (unsigned xi = 1; xi < ds_; xi++) { - if (ldVals_[xi] != ldVals_[0]) { - childInfluenced = true; - break; - } - } - return childInfluenced; -} - diff --git a/packages/CLPBN/clpbn/bp/BPNodeInfo.h b/packages/CLPBN/clpbn/bp/BPNodeInfo.h deleted file mode 100755 index 966702652..000000000 --- a/packages/CLPBN/clpbn/bp/BPNodeInfo.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef BP_BP_NODE_H -#define BP_BP_NODE_H - -#include -#include - -#include "BPSolver.h" -#include "BayesNode.h" -#include "Shared.h" - -//class Edge; - -using namespace std; - -class BPNodeInfo -{ - public: - BPNodeInfo (int); - BPNodeInfo (BayesNode*); - - ParamSet getBeliefs (void) const; - double getPiValue (unsigned) const; - void setPiValue (unsigned, Param); - double getLambdaValue (unsigned) const; - void setLambdaValue (unsigned, Param); - double getBeliefChange (void); - bool receivedBottomInfluence (void) const; - - ParamSet& getPiValues (void) { return piVals_; } - ParamSet& getLambdaValues (void) { return ldVals_; } - bool arePiValuesCalculated (void) { return piValsCalc_; } - bool areLambdaValuesCalculated (void) { return ldValsCalc_; } - void markPiValuesAsCalculated (void) { piValsCalc_ = true; } - void markLambdaValuesAsCalculated (void) { ldValsCalc_ = true; } - void incNumPiMsgsRcv (void) { nPiMsgsRcv_ ++; } - void incNumLambdaMsgsRcv (void) { nLdMsgsRcv_ ++; } - - bool receivedAllPiMessages (void) - { - return node_->getParents().size() == nPiMsgsRcv_; - } - - bool receivedAllLambdaMessages (void) - { - return node_->getChilds().size() == nLdMsgsRcv_; - } - - bool readyToSendPiMsgTo (const BayesNode*) const ; - bool readyToSendLambdaMsgTo (const BayesNode*) const; - - CEdgeSet getIncomingParentLinks (void) { return inParentLinks_; } - CEdgeSet getIncomingChildLinks (void) { return inChildLinks_; } - CEdgeSet getOutcomingParentLinks (void) { return outParentLinks_; } - CEdgeSet getOutcomingChildLinks (void) { return outChildLinks_; } - - void addIncomingParentLink (Edge* l) { inParentLinks_.push_back (l); } - void addIncomingChildLink (Edge* l) { inChildLinks_.push_back (l); } - void addOutcomingParentLink (Edge* l) { outParentLinks_.push_back (l); } - void addOutcomingChildLink (Edge* l) { outChildLinks_.push_back (l); } - - private: - DISALLOW_COPY_AND_ASSIGN (BPNodeInfo); - - ParamSet piVals_; // pi values - ParamSet ldVals_; // lambda values - ParamSet oldBeliefs_; - unsigned nPiMsgsRcv_; - unsigned nLdMsgsRcv_; - bool piValsCalc_; - bool ldValsCalc_; - EdgeSet inParentLinks_; - EdgeSet inChildLinks_; - EdgeSet outParentLinks_; - EdgeSet outChildLinks_; - unsigned ds_; - const BayesNode* node_; - map pmsgs_; - map cmsgs_; -}; - -#endif //BP_BP_NODE_H - diff --git a/packages/CLPBN/clpbn/bp/BPSolver.cpp b/packages/CLPBN/clpbn/bp/BPSolver.cpp deleted file mode 100644 index 67407d80c..000000000 --- a/packages/CLPBN/clpbn/bp/BPSolver.cpp +++ /dev/null @@ -1,905 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include "BPSolver.h" - -BPSolver::BPSolver (const BayesNet& bn) : Solver (&bn) -{ - bn_ = &bn; - useAlwaysLoopySolver_ = false; - //jointCalcType_ = CHAIN_RULE; - jointCalcType_ = JUNCTION_NODE; -} - - - -BPSolver::~BPSolver (void) -{ - for (unsigned i = 0; i < nodesI_.size(); i++) { - delete nodesI_[i]; - } - for (unsigned i = 0; i < links_.size(); i++) { - delete links_[i]; - } -} - - - -void -BPSolver::runSolver (void) -{ - clock_t start_ = clock(); - unsigned size = bn_->getNumberOfNodes(); - unsigned nIters = 0; - initializeSolver(); - if (bn_->isSingleConnected() && !useAlwaysLoopySolver_) { - runPolyTreeSolver(); - Statistics::numSolvedPolyTrees ++; - } else { - runLoopySolver(); - Statistics::numSolvedLoopyNets ++; - if (nIter_ >= SolverOptions::maxIter) { - Statistics::numUnconvergedRuns ++; - } else { - nIters = nIter_; - } - if (DL >= 2) { - cout << endl; - if (nIter_ < SolverOptions::maxIter) { - cout << "Belief propagation converged in " ; - cout << nIter_ << " iterations" << endl; - } else { - cout << "The maximum number of iterations was hit, terminating..." ; - cout << endl; - } - } - } - double time = (double (clock() - start_)) / CLOCKS_PER_SEC; - Statistics::updateStats (size, nIters, time); - if (EXPORT_TO_DOT && size > EXPORT_MIN_SIZE) { - stringstream ss; - ss << size << "." ; - ss << Statistics::getCounting (size) << ".dot" ; - bn_->exportToDotFormat (ss.str().c_str()); - } -} - - - -ParamSet -BPSolver::getPosterioriOf (Vid vid) const -{ - BayesNode* node = bn_->getBayesNode (vid); - assert (node); - return nodesI_[node->getIndex()]->getBeliefs(); -} - - - -ParamSet -BPSolver::getJointDistributionOf (const VidSet& jointVids) -{ - if (DL >= 2) { - cout << "calculating joint distribution on: " ; - for (unsigned i = 0; i < jointVids.size(); i++) { - Variable* var = bn_->getBayesNode (jointVids[i]); - cout << var->getLabel() << " " ; - } - cout << endl; - } - - if (jointCalcType_ == JUNCTION_NODE) { - return getJointByJunctionNode (jointVids); - } else { - return getJointByChainRule (jointVids); - } -} - - - -void -BPSolver::initializeSolver (void) -{ - if (DL >= 2) { - if (!useAlwaysLoopySolver_) { - cout << "-> solver type = polytree solver" << endl; - cout << "-> schedule = n/a"; - } else { - cout << "-> solver = loopy solver" << endl; - cout << "-> schedule = "; - switch (SolverOptions::schedule) { - case SolverOptions::S_SEQ_FIXED: cout << "sequential fixed" ; break; - case SolverOptions::S_SEQ_RANDOM: cout << "sequential random" ; break; - case SolverOptions::S_PARALLEL: cout << "parallel" ; break; - case SolverOptions::S_MAX_RESIDUAL: cout << "max residual" ; break; - } - } - cout << endl; - cout << "-> joint method = " ; - if (jointCalcType_ == JUNCTION_NODE) { - cout << "junction node" << endl; - } else { - cout << "chain rule " << endl; - } - cout << "-> max iters = " << SolverOptions::maxIter << endl; - cout << "-> accuracy = " << SolverOptions::accuracy << endl; - cout << endl; - } - - CBnNodeSet nodes = bn_->getBayesNodes(); - for (unsigned i = 0; i < nodesI_.size(); i++) { - delete nodesI_[i]; - } - nodesI_.clear(); - nodesI_.reserve (nodes.size()); - links_.clear(); - sortedOrder_.clear(); - edgeMap_.clear(); - - for (unsigned i = 0; i < nodes.size(); i++) { - nodesI_.push_back (new BPNodeInfo (nodes[i])); - } - - BnNodeSet roots = bn_->getRootNodes(); - for (unsigned i = 0; i < roots.size(); i++) { - const ParamSet& params = roots[i]->getParameters(); - ParamSet& piVals = M(roots[i])->getPiValues(); - for (unsigned ri = 0; ri < roots[i]->getDomainSize(); ri++) { - piVals[ri] = params[ri]; - } - } - - for (unsigned i = 0; i < nodes.size(); i++) { - CBnNodeSet parents = nodes[i]->getParents(); - for (unsigned j = 0; j < parents.size(); j++) { - Edge* newLink = new Edge (parents[j], nodes[i], PI_MSG); - links_.push_back (newLink); - M(nodes[i])->addIncomingParentLink (newLink); - M(parents[j])->addOutcomingChildLink (newLink); - } - CBnNodeSet childs = nodes[i]->getChilds(); - for (unsigned j = 0; j < childs.size(); j++) { - Edge* newLink = new Edge (childs[j], nodes[i], LAMBDA_MSG); - links_.push_back (newLink); - M(nodes[i])->addIncomingChildLink (newLink); - M(childs[j])->addOutcomingParentLink (newLink); - } - } - - for (unsigned i = 0; i < nodes.size(); i++) { - if (nodes[i]->hasEvidence()) { - ParamSet& piVals = M(nodes[i])->getPiValues(); - ParamSet& ldVals = M(nodes[i])->getLambdaValues(); - for (unsigned xi = 0; xi < nodes[i]->getDomainSize(); xi++) { - piVals[xi] = 0.0; - ldVals[xi] = 0.0; - } - piVals[nodes[i]->getEvidence()] = 1.0; - ldVals[nodes[i]->getEvidence()] = 1.0; - } - } -} - - - -void -BPSolver::runPolyTreeSolver (void) -{ - CBnNodeSet nodes = bn_->getBayesNodes(); - for (unsigned i = 0; i < nodes.size(); i++) { - if (nodes[i]->isRoot()) { - M(nodes[i])->markPiValuesAsCalculated(); - } - if (nodes[i]->isLeaf()) { - M(nodes[i])->markLambdaValuesAsCalculated(); - } - } - - bool finish = false; - while (!finish) { - finish = true; - for (unsigned i = 0; i < nodes.size(); i++) { - if (M(nodes[i])->arePiValuesCalculated() == false - && M(nodes[i])->receivedAllPiMessages()) { - if (!nodes[i]->hasEvidence()) { - updatePiValues (nodes[i]); - } - M(nodes[i])->markPiValuesAsCalculated(); - finish = false; - } - - if (M(nodes[i])->areLambdaValuesCalculated() == false - && M(nodes[i])->receivedAllLambdaMessages()) { - if (!nodes[i]->hasEvidence()) { - updateLambdaValues (nodes[i]); - } - M(nodes[i])->markLambdaValuesAsCalculated(); - finish = false; - } - - if (M(nodes[i])->arePiValuesCalculated()) { - CEdgeSet outChildLinks = M(nodes[i])->getOutcomingChildLinks(); - for (unsigned j = 0; j < outChildLinks.size(); j++) { - BayesNode* child = outChildLinks[j]->getDestination(); - if (!outChildLinks[j]->messageWasSended()) { - if (M(nodes[i])->readyToSendPiMsgTo (child)) { - outChildLinks[j]->setNextMessage (getMessage (outChildLinks[j])); - outChildLinks[j]->updateMessage(); - M(child)->incNumPiMsgsRcv(); - } - finish = false; - } - } - } - - if (M(nodes[i])->areLambdaValuesCalculated()) { - CEdgeSet outParentLinks = M(nodes[i])->getOutcomingParentLinks(); - for (unsigned j = 0; j < outParentLinks.size(); j++) { - BayesNode* parent = outParentLinks[j]->getDestination(); - if (!outParentLinks[j]->messageWasSended()) { - if (M(nodes[i])->readyToSendLambdaMsgTo (parent)) { - outParentLinks[j]->setNextMessage (getMessage (outParentLinks[j])); - outParentLinks[j]->updateMessage(); - M(parent)->incNumLambdaMsgsRcv(); - } - finish = false; - } - } - } - } - } -} - - - -void -BPSolver::runLoopySolver() -{ - nIter_ = 0; - while (!converged() && nIter_ < SolverOptions::maxIter) { - - nIter_++; - if (DL >= 2) { - cout << endl; - cout << "****************************************" ; - cout << "****************************************" ; - cout << endl; - cout << " Iteration " << nIter_ << endl; - cout << "****************************************" ; - cout << "****************************************" ; - cout << endl; - } - - switch (SolverOptions::schedule) { - - case SolverOptions::S_SEQ_RANDOM: - random_shuffle (links_.begin(), links_.end()); - // no break - - case SolverOptions::S_SEQ_FIXED: - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->setNextMessage (getMessage (links_[i])); - links_[i]->updateMessage(); - updateValues (links_[i]); - } - break; - - case SolverOptions::S_PARALLEL: - for (unsigned i = 0; i < links_.size(); i++) { - //calculateNextMessage (links_[i]); - } - for (unsigned i = 0; i < links_.size(); i++) { - //updateMessage (links_[i]); - //updateValues (links_[i]); - } - break; - - case SolverOptions::S_MAX_RESIDUAL: - maxResidualSchedule(); - break; - - } - } -} - - - -bool -BPSolver::converged (void) const -{ - // this can happen if the graph is fully disconnected - if (links_.size() == 0) { - return true; - } - if (nIter_ == 0 || nIter_ == 1) { - return false; - } - bool converged = true; - if (SolverOptions::schedule == SolverOptions::S_MAX_RESIDUAL) { - Param maxResidual = (*(sortedOrder_.begin()))->getResidual(); - if (maxResidual < SolverOptions::accuracy) { - converged = true; - } else { - converged = false; - } - } else { - CBnNodeSet nodes = bn_->getBayesNodes(); - for (unsigned i = 0; i < nodes.size(); i++) { - if (!nodes[i]->hasEvidence()) { - double change = M(nodes[i])->getBeliefChange(); - if (DL >= 2) { - cout << nodes[i]->getLabel() + " belief change = " ; - cout << change << endl; - } - if (change > SolverOptions::accuracy) { - converged = false; - if (DL == 0) break; - } - } - } - } - return converged; -} - - - -void -BPSolver::maxResidualSchedule (void) -{ - if (nIter_ == 1) { - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->setNextMessage (getMessage (links_[i])); - links_[i]->updateResidual(); - SortedOrder::iterator it = sortedOrder_.insert (links_[i]); - edgeMap_.insert (make_pair (links_[i], it)); - if (DL >= 2) { - cout << "calculating " << links_[i]->toString() << endl; - } - } - return; - } - - for (unsigned c = 0; c < sortedOrder_.size(); c++) { - if (DL >= 2) { - cout << endl << "current residuals:" << endl; - for (SortedOrder::iterator it = sortedOrder_.begin(); - it != sortedOrder_.end(); it ++) { - cout << " " << setw (30) << left << (*it)->toString(); - cout << "residual = " << (*it)->getResidual() << endl; - } - } - - SortedOrder::iterator it = sortedOrder_.begin(); - Edge* edge = *it; - if (DL >= 2) { - cout << "updating " << edge->toString() << endl; - } - if (edge->getResidual() < SolverOptions::accuracy) { - return; - } - edge->updateMessage(); - updateValues (edge); - edge->clearResidual(); - sortedOrder_.erase (it); - edgeMap_.find (edge)->second = sortedOrder_.insert (edge); - - // update the messages that depend on message source --> destin - CEdgeSet outChildLinks = - M(edge->getDestination())->getOutcomingChildLinks(); - for (unsigned i = 0; i < outChildLinks.size(); i++) { - if (outChildLinks[i]->getDestination() != edge->getSource()) { - if (DL >= 2) { - cout << " calculating " << outChildLinks[i]->toString() << endl; - } - outChildLinks[i]->setNextMessage (getMessage (outChildLinks[i])); - outChildLinks[i]->updateResidual(); - EdgeMap::iterator iter = edgeMap_.find (outChildLinks[i]); - sortedOrder_.erase (iter->second); - iter->second = sortedOrder_.insert (outChildLinks[i]); - } - } - CEdgeSet outParentLinks = - M(edge->getDestination())->getOutcomingParentLinks(); - for (unsigned i = 0; i < outParentLinks.size(); i++) { - if (outParentLinks[i]->getDestination() != edge->getSource()) { - //&& !outParentLinks[i]->getDestination()->hasEvidence()) FIXME{ - if (DL >= 2) { - cout << " calculating " << outParentLinks[i]->toString() << endl; - } - outParentLinks[i]->setNextMessage (getMessage (outParentLinks[i])); - outParentLinks[i]->updateResidual(); - EdgeMap::iterator iter = edgeMap_.find (outParentLinks[i]); - sortedOrder_.erase (iter->second); - iter->second = sortedOrder_.insert (outParentLinks[i]); - } - } - - } -} - - - -void -BPSolver::updatePiValues (BayesNode* x) -{ - // π(Xi) - if (DL >= 3) { - cout << "updating " << PI << " values for " << x->getLabel() << endl; - } - CEdgeSet parentLinks = M(x)->getIncomingParentLinks(); - assert (x->getParents() == parentLinks.size()); - const vector& entries = x->getCptEntries(); - stringstream* calcs1 = 0; - stringstream* calcs2 = 0; - - ParamSet messageProducts (entries.size()); - for (unsigned k = 0; k < entries.size(); k++) { - if (DL >= 5) { - calcs1 = new stringstream; - calcs2 = new stringstream; - } - double messageProduct = 1.0; - const DConf& conf = entries[k].getDomainConfiguration(); - for (unsigned i = 0; i < parentLinks.size(); i++) { - assert (parentLinks[i]->getSource() == parents[i]); - assert (parentLinks[i]->getDestination() == x); - messageProduct *= parentLinks[i]->getMessage()[conf[i]]; - if (DL >= 5) { - if (i != 0) *calcs1 << "." ; - if (i != 0) *calcs2 << "*" ; - *calcs1 << PI << "(" << parentLinks[i]->getSource()->getLabel(); - *calcs1 << " --> " << x->getLabel() << ")" ; - *calcs1 << "[" ; - *calcs1 << parentLinks[i]->getSource()->getDomain()[conf[i]]; - *calcs1 << "]"; - *calcs2 << parentLinks[i]->getMessage()[conf[i]]; - } - } - messageProducts[k] = messageProduct; - if (DL >= 5) { - cout << " mp" << k; - cout << " = " << (*calcs1).str(); - if (parentLinks.size() == 1) { - cout << " = " << messageProduct << endl; - } else { - cout << " = " << (*calcs2).str(); - cout << " = " << messageProduct << endl; - } - delete calcs1; - delete calcs2; - } - } - - for (unsigned xi = 0; xi < x->getDomainSize(); xi++) { - double sum = 0.0; - if (DL >= 5) { - calcs1 = new stringstream; - calcs2 = new stringstream; - } - for (unsigned k = 0; k < entries.size(); k++) { - sum += x->getProbability (xi, entries[k]) * messageProducts[k]; - if (DL >= 5) { - if (k != 0) *calcs1 << " + " ; - if (k != 0) *calcs2 << " + " ; - *calcs1 << x->cptEntryToString (xi, entries[k]); - *calcs1 << ".mp" << k; - *calcs2 << x->getProbability (xi, entries[k]); - *calcs2 << "*" << messageProducts[k]; - } - } - M(x)->setPiValue (xi, sum); - if (DL >= 5) { - cout << " " << PI << "(" << x->getLabel() << ")" ; - cout << "[" << x->getDomain()[xi] << "]" ; - cout << " = " << (*calcs1).str(); - cout << " = " << (*calcs2).str(); - cout << " = " << sum << endl; - delete calcs1; - delete calcs2; - } - } -} - - - -void -BPSolver::updateLambdaValues (BayesNode* x) -{ - // λ(Xi) - if (DL >= 3) { - cout << "updating " << LD << " values for " << x->getLabel() << endl; - } - CEdgeSet childLinks = M(x)->getIncomingChildLinks(); - stringstream* calcs1 = 0; - stringstream* calcs2 = 0; - - for (unsigned xi = 0; xi < x->getDomainSize(); xi++) { - double product = 1.0; - if (DL >= 5) { - calcs1 = new stringstream; - calcs2 = new stringstream; - } - for (unsigned i = 0; i < childLinks.size(); i++) { - assert (childLinks[i]->getDestination() == x); - product *= childLinks[i]->getMessage()[xi]; - if (DL >= 5) { - if (i != 0) *calcs1 << "." ; - if (i != 0) *calcs2 << "*" ; - *calcs1 << LD << "(" << childLinks[i]->getSource()->getLabel(); - *calcs1 << "-->" << x->getLabel() << ")" ; - *calcs1 << "[" << x->getDomain()[xi] << "]" ; - *calcs2 << childLinks[i]->getMessage()[xi]; - } - } - M(x)->setLambdaValue (xi, product); - if (DL >= 5) { - cout << " " << LD << "(" << x->getLabel() << ")" ; - cout << "[" << x->getDomain()[xi] << "]" ; - cout << " = " << (*calcs1).str(); - if (childLinks.size() == 1) { - cout << " = " << product << endl; - } else { - cout << " = " << (*calcs2).str(); - cout << " = " << product << endl; - } - delete calcs1; - delete calcs2; - } - } -} - - - -ParamSet -BPSolver::calculateNextPiMessage (Edge* edge) -{ - // πX(Zi) - BayesNode* z = edge->getSource(); - BayesNode* x = edge->getDestination(); - ParamSet zxPiNextMessage (z->getDomainSize()); - CEdgeSet zChildLinks = M(z)->getIncomingChildLinks(); - stringstream* calcs1 = 0; - stringstream* calcs2 = 0; - - - for (unsigned zi = 0; zi < z->getDomainSize(); zi++) { - double product = M(z)->getPiValue (zi); - if (DL >= 5) { - calcs1 = new stringstream; - calcs2 = new stringstream; - *calcs1 << PI << "(" << z->getLabel() << ")"; - *calcs1 << "[" << z->getDomain()[zi] << "]" ; - *calcs2 << product; - } - for (unsigned i = 0; i < zChildLinks.size(); i++) { - assert (zChildLinks[i]->getDestination() == z); - if (zChildLinks[i]->getSource() != x) { - product *= zChildLinks[i]->getMessage()[zi]; - if (DL >= 5) { - *calcs1 << "." << LD << "(" << zChildLinks[i]->getSource()->getLabel(); - *calcs1 << "-->" << z->getLabel() << ")"; - *calcs1 << "[" << z->getDomain()[zi] + "]" ; - *calcs2 << " * " << zChildLinks[i]->getMessage()[zi]; - } - } - } - zxPiNextMessage[zi] = product; - if (DL >= 5) { - cout << " " << PI << "(" << z->getLabel(); - cout << "-->" << x->getLabel() << ")" ; - cout << "[" << z->getDomain()[zi] << "]" ; - cout << " = " << (*calcs1).str(); - if (zChildLinks.size() == 1) { - cout << " = " << product << endl; - } else { - cout << " = " << (*calcs2).str(); - cout << " = " << product << endl; - } - delete calcs1; - delete calcs2; - } - } - return zxPiNextMessage; -} - - - -ParamSet -BPSolver::calculateNextLambdaMessage (Edge* edge) -{ - // λY(Xi) - BayesNode* y = edge->getSource(); - BayesNode* x = edge->getDestination(); - if (!M(y)->receivedBottomInfluence()) { - //cout << "returning 1" << endl; - //return edge->getMessage(); - } - if (x->hasEvidence()) { - //cout << "returning 2" << endl; - //return edge->getMessage(); - } - ParamSet yxLambdaNextMessage (x->getDomainSize()); - CEdgeSet yParentLinks = M(y)->getIncomingParentLinks(); - const vector& allEntries = y->getCptEntries(); - int parentIndex = y->getIndexOfParent (x); - stringstream* calcs1 = 0; - stringstream* calcs2 = 0; - - vector entries; - DConstraint constr = make_pair (parentIndex, 0); - for (unsigned i = 0; i < allEntries.size(); i++) { - if (allEntries[i].matchConstraints(constr)) { - entries.push_back (allEntries[i]); - } - } - - ParamSet messageProducts (entries.size()); - for (unsigned k = 0; k < entries.size(); k++) { - if (DL >= 5) { - calcs1 = new stringstream; - calcs2 = new stringstream; - } - double messageProduct = 1.0; - const DConf& conf = entries[k].getDomainConfiguration(); - for (unsigned i = 0; i < yParentLinks.size(); i++) { - assert (yParentLinks[i]->getDestination() == y); - if (yParentLinks[i]->getSource() != x) { - if (DL >= 5) { - if (messageProduct != 1.0) *calcs1 << "*" ; - if (messageProduct != 1.0) *calcs2 << "*" ; - *calcs1 << PI << "(" << yParentLinks[i]->getSource()->getLabel(); - *calcs1 << "-->" << y->getLabel() << ")" ; - *calcs1 << "[" ; - *calcs1 << yParentLinks[i]->getSource()->getDomain()[conf[i]]; - *calcs1 << "]" ; - *calcs2 << yParentLinks[i]->getMessage()[conf[i]]; - } - messageProduct *= yParentLinks[i]->getMessage()[conf[i]]; - } - } - messageProducts[k] = messageProduct; - if (DL >= 5) { - cout << " mp" << k; - cout << " = " << (*calcs1).str(); - if (yParentLinks.size() == 1) { - cout << 1 << endl; - } else if (yParentLinks.size() == 2) { - cout << " = " << messageProduct << endl; - } else { - cout << " = " << (*calcs2).str(); - cout << " = " << messageProduct << endl; - } - delete calcs1; - delete calcs2; - } - } - - for (unsigned xi = 0; xi < x->getDomainSize(); xi++) { - if (DL >= 5) { - calcs1 = new stringstream; - calcs2 = new stringstream; - } - vector entries; - DConstraint constr = make_pair (parentIndex, xi); - for (unsigned i = 0; i < allEntries.size(); i++) { - if (allEntries[i].matchConstraints(constr)) { - entries.push_back (allEntries[i]); - } - } - double outerSum = 0.0; - for (unsigned yi = 0; yi < y->getDomainSize(); yi++) { - if (DL >= 5) { - (yi != 0) ? *calcs1 << " + {" : *calcs1 << "{" ; - (yi != 0) ? *calcs2 << " + {" : *calcs2 << "{" ; - } - double innerSum = 0.0; - for (unsigned k = 0; k < entries.size(); k++) { - if (DL >= 5) { - if (k != 0) *calcs1 << " + " ; - if (k != 0) *calcs2 << " + " ; - *calcs1 << y->cptEntryToString (yi, entries[k]); - *calcs1 << ".mp" << k; - *calcs2 << y->getProbability (yi, entries[k]); - *calcs2 << "*" << messageProducts[k]; - } - innerSum += y->getProbability (yi, entries[k]) * messageProducts[k]; - } - outerSum += innerSum * M(y)->getLambdaValue (yi); - if (DL >= 5) { - *calcs1 << "}." << LD << "(" << y->getLabel() << ")" ; - *calcs1 << "[" << y->getDomain()[yi] << "]"; - *calcs2 << "}*" << M(y)->getLambdaValue (yi); - } - } - yxLambdaNextMessage[xi] = outerSum; - if (DL >= 5) { - cout << " " << LD << "(" << y->getLabel(); - cout << "-->" << x->getLabel() << ")" ; - cout << "[" << x->getDomain()[xi] << "]" ; - cout << " = " << (*calcs1).str(); - cout << " = " << (*calcs2).str(); - cout << " = " << outerSum << endl; - delete calcs1; - delete calcs2; - } - } - return yxLambdaNextMessage; -} - - - -ParamSet -BPSolver::getJointByJunctionNode (const VidSet& jointVids) const -{ - BnNodeSet jointVars; - for (unsigned i = 0; i < jointVids.size(); i++) { - jointVars.push_back (bn_->getBayesNode (jointVids[i])); - } - - BayesNet* mrn = bn_->getMinimalRequesiteNetwork (jointVids); - - BnNodeSet parents; - unsigned dsize = 1; - for (unsigned i = 0; i < jointVars.size(); i++) { - parents.push_back (mrn->getBayesNode (jointVids[i])); - dsize *= jointVars[i]->getDomainSize(); - } - - unsigned nParams = dsize * dsize; - ParamSet params (nParams); - - for (unsigned i = 0; i < nParams; i++) { - unsigned row = i / dsize; - unsigned col = i % dsize; - if (row == col) { - params[i] = 1; - } else { - params[i] = 0; - } - } - - unsigned maxVid = std::numeric_limits::max(); - Distribution* dist = new Distribution (params); - - mrn->addNode (maxVid, dsize, NO_EVIDENCE, parents, dist); - mrn->setIndexes(); - - BPSolver solver (*mrn); - solver.runSolver(); - - const ParamSet& results = solver.getPosterioriOf (maxVid); - - delete mrn; - delete dist; - - return results; -} - - - -ParamSet -BPSolver::getJointByChainRule (const VidSet& jointVids) const -{ - BnNodeSet jointVars; - for (unsigned i = 0; i < jointVids.size(); i++) { - jointVars.push_back (bn_->getBayesNode (jointVids[i])); - } - - BayesNet* mrn = bn_->getMinimalRequesiteNetwork (jointVids[0]); - BPSolver solver (*mrn); - solver.runSolver(); - ParamSet prevBeliefs = solver.getPosterioriOf (jointVids[0]); - delete mrn; - - VarSet observedVars = {jointVars[0]}; - - for (unsigned i = 1; i < jointVids.size(); i++) { - mrn = bn_->getMinimalRequesiteNetwork (jointVids[i]); - ParamSet newBeliefs; - vector confs = - Util::getDomainConfigurations (observedVars); - for (unsigned j = 0; j < confs.size(); j++) { - for (unsigned k = 0; k < observedVars.size(); k++) { - if (!observedVars[k]->hasEvidence()) { - BayesNode* node = mrn->getBayesNode (observedVars[k]->getVarId()); - if (node) { - node->setEvidence (confs[j][k]); - } - } - } - BPSolver solver (*mrn); - solver.runSolver(); - ParamSet beliefs = solver.getPosterioriOf (jointVids[i]); - for (unsigned k = 0; k < beliefs.size(); k++) { - newBeliefs.push_back (beliefs[k]); - } - } - - int count = -1; - for (unsigned j = 0; j < newBeliefs.size(); j++) { - if (j % jointVars[i]->getDomainSize() == 0) { - count ++; - } - newBeliefs[j] *= prevBeliefs[count]; - } - prevBeliefs = newBeliefs; - observedVars.push_back (jointVars[i]); - delete mrn; - } - return prevBeliefs; -} - - - -void -BPSolver::printMessageStatusOf (const BayesNode* var) const -{ - cout << left; - cout << setw (10) << "domain" ; - cout << setw (20) << PI << "(" + var->getLabel() + ")" ; - cout << setw (20) << LD << "(" + var->getLabel() + ")" ; - cout << setw (16) << "belief" ; - cout << endl; - cout << "--------------------------------" ; - cout << "--------------------------------" ; - cout << endl; - - BPNodeInfo* x = M(var); - ParamSet& piVals = x->getPiValues(); - ParamSet& ldVals = x->getLambdaValues(); - ParamSet beliefs = x->getBeliefs(); - const Domain& domain = var->getDomain(); - CBnNodeSet& childs = var->getChilds(); - - for (unsigned xi = 0; xi < var->getDomainSize(); xi++) { - cout << setw (10) << domain[xi]; - cout << setw (19) << piVals[xi]; - cout << setw (19) << ldVals[xi]; - cout.precision (PRECISION); - cout << setw (16) << beliefs[xi]; - cout << endl; - } - cout << endl; - if (childs.size() > 0) { - string s = "(" + var->getLabel() + ")" ; - for (unsigned j = 0; j < childs.size(); j++) { - cout << setw (10) << "domain" ; - cout << setw (28) << PI + childs[j]->getLabel() + s; - cout << setw (28) << LD + childs[j]->getLabel() + s; - cout << endl; - cout << "--------------------------------" ; - cout << "--------------------------------" ; - cout << endl; - /* FIXME - const ParamSet& piMessage = x->getPiMessage (childs[j]); - const ParamSet& lambdaMessage = x->getLambdaMessage (childs[j]); - for (unsigned xi = 0; xi < var->getDomainSize(); xi++) { - cout << setw (10) << domain[xi]; - cout.precision (PRECISION); - cout << setw (27) << piMessage[xi]; - cout.precision (PRECISION); - cout << setw (27) << lambdaMessage[xi]; - cout << endl; - } - cout << endl; - */ - } - } -} - - - -void -BPSolver::printAllMessageStatus (void) const -{ - CBnNodeSet nodes = bn_->getBayesNodes(); - for (unsigned i = 0; i < nodes.size(); i++) { - printMessageStatusOf (nodes[i]); - } -} - diff --git a/packages/CLPBN/clpbn/bp/BPSolver.h b/packages/CLPBN/clpbn/bp/BPSolver.h deleted file mode 100644 index c3b8ee9f1..000000000 --- a/packages/CLPBN/clpbn/bp/BPSolver.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef BP_BP_SOLVER_H -#define BP_BP_SOLVER_H - -#include -#include - -#include "Solver.h" -#include "BayesNet.h" -#include "BPNodeInfo.h" -#include "Shared.h" - -using namespace std; - -class BPNodeInfo; - -static const string PI = "pi" ; -static const string LD = "ld" ; - - -enum MessageType {PI_MSG, LAMBDA_MSG}; -enum JointCalcType {CHAIN_RULE, JUNCTION_NODE}; - -class Edge -{ - public: - Edge (BayesNode* s, BayesNode* d, MessageType t) - { - source_ = s; - destin_ = d; - type_ = t; - if (type_ == PI_MSG) { - currMsg_.resize (s->getDomainSize(), 1); - nextMsg_.resize (s->getDomainSize(), 1); - } else { - currMsg_.resize (d->getDomainSize(), 1); - nextMsg_.resize (d->getDomainSize(), 1); - } - msgSended_ = false; - residual_ = 0.0; - } - - //void setMessage (ParamSet msg) - //{ - // Util::normalize (msg); - // residual_ = Util::getMaxNorm (currMsg_, msg); - // currMsg_ = msg; - //} - - void setNextMessage (CParamSet msg) - { - nextMsg_ = msg; - Util::normalize (nextMsg_); - residual_ = Util::getMaxNorm (currMsg_, nextMsg_); - } - - void updateMessage (void) - { - currMsg_ = nextMsg_; - if (DL >= 3) { - cout << "updating " << toString() << endl; - } - msgSended_ = true; - } - - void updateResidual (void) - { - residual_ = Util::getMaxNorm (currMsg_, nextMsg_); - } - - string toString (void) const - { - stringstream ss; - if (type_ == PI_MSG) { - ss << PI; - } else if (type_ == LAMBDA_MSG) { - ss << LD; - } else { - abort(); - } - ss << "(" << source_->getLabel(); - ss << " --> " << destin_->getLabel() << ")" ; - return ss.str(); - } - - BayesNode* getSource (void) const { return source_; } - BayesNode* getDestination (void) const { return destin_; } - MessageType getMessageType (void) const { return type_; } - CParamSet getMessage (void) const { return currMsg_; } - bool messageWasSended (void) const { return msgSended_; } - double getResidual (void) const { return residual_; } - void clearResidual (void) { residual_ = 0.0; } - - private: - BayesNode* source_; - BayesNode* destin_; - MessageType type_; - ParamSet currMsg_; - ParamSet nextMsg_; - bool msgSended_; - double residual_; -}; - - -class BPSolver : public Solver -{ - public: - BPSolver (const BayesNet&); - ~BPSolver (void); - - void runSolver (void); - ParamSet getPosterioriOf (Vid) const; - ParamSet getJointDistributionOf (const VidSet&); - - - private: - DISALLOW_COPY_AND_ASSIGN (BPSolver); - - void initializeSolver (void); - void runPolyTreeSolver (void); - void runLoopySolver (void); - void maxResidualSchedule (void); - bool converged (void) const; - void updatePiValues (BayesNode*); - void updateLambdaValues (BayesNode*); - ParamSet calculateNextLambdaMessage (Edge* edge); - ParamSet calculateNextPiMessage (Edge* edge); - ParamSet getJointByJunctionNode (const VidSet&) const; - ParamSet getJointByChainRule (const VidSet&) const; - void printMessageStatusOf (const BayesNode*) const; - void printAllMessageStatus (void) const; - - ParamSet getMessage (Edge* edge) - { - if (DL >= 3) { - cout << " calculating " << edge->toString() << endl; - } - if (edge->getMessageType() == PI_MSG) { - return calculateNextPiMessage (edge); - } else if (edge->getMessageType() == LAMBDA_MSG) { - return calculateNextLambdaMessage (edge); - } else { - abort(); - } - return ParamSet(); - } - - void updateValues (Edge* edge) - { - if (!edge->getDestination()->hasEvidence()) { - if (edge->getMessageType() == PI_MSG) { - updatePiValues (edge->getDestination()); - } else if (edge->getMessageType() == LAMBDA_MSG) { - updateLambdaValues (edge->getDestination()); - } else { - abort(); - } - } - } - - BPNodeInfo* M (const BayesNode* node) const - { - assert (node); - assert (node == bn_->getBayesNode (node->getVarId())); - assert (node->getIndex() < nodesI_.size()); - return nodesI_[node->getIndex()]; - } - - const BayesNet* bn_; - vector nodesI_; - unsigned nIter_; - vector links_; - bool useAlwaysLoopySolver_; - JointCalcType jointCalcType_; - - struct compare - { - inline bool operator() (const Edge* e1, const Edge* e2) - { - return e1->getResidual() > e2->getResidual(); - } - }; - - typedef multiset SortedOrder; - SortedOrder sortedOrder_; - - typedef map EdgeMap; - EdgeMap edgeMap_; - -}; - -#endif //BP_BP_SOLVER_H - diff --git a/packages/CLPBN/clpbn/bp/BpNetwork.cpp b/packages/CLPBN/clpbn/bp/BpNetwork.cpp deleted file mode 100644 index 905f7cbc3..000000000 --- a/packages/CLPBN/clpbn/bp/BpNetwork.cpp +++ /dev/null @@ -1,811 +0,0 @@ -#include -#include -#include -#include - -#include "BpNetwork.h" -#include "BpNode.h" -#include "CptEntry.h" - -BpNetwork::BpNetwork (void) -{ - schedule_ = SEQUENTIAL_SCHEDULE; - maxIter_ = 150; - stableThreashold_ = 0.00000000000000000001; -} - - - -BpNetwork::~BpNetwork (void) -{ - for (unsigned int i = 0; i < nodes_.size(); i++) { - delete nodes_[i]; - } - nodes_.clear(); -} - - - -void -BpNetwork::setSolverParameters (Schedule schedule, - int maxIter, - double stableThreashold) -{ - if (maxIter <= 0) { - cerr << "error: maxIter must be greater or equal to 1" << endl; - abort(); - } - if (stableThreashold <= 0.0 || stableThreashold >= 1.0) { - cerr << "error: stableThreashold must be greater than 0.0 " ; - cerr << "and lesser than 1.0" << endl; - abort(); - } - schedule_ = schedule; - maxIter_ = maxIter; - stableThreashold_ = stableThreashold; -} - - - -void -BpNetwork::runSolver (BayesianNode* queryVar) -{ - vector queryVars; - queryVars.push_back (queryVar); - runSolver (queryVars); -} - - - -void -BpNetwork::runSolver (vector queryVars) -{ - if (queryVars.size() > 1) { - addJunctionNode (queryVars); - } - else { - string varName = queryVars[0]->getVariableName(); - queryNode_ = static_cast (getNode (varName)); - } - - if (!isPolyTree()) { - if (DL_ >= 1) { - cout << "The graph is not single connected. " ; - cout << "Iterative belief propagation will be used." ; - cout << endl << endl; - } - schedule_ = PARALLEL_SCHEDULE; - } - - if (schedule_ == SEQUENTIAL_SCHEDULE) { - initializeSolver (queryVars); - runNeapolitanSolver(); - for (unsigned int i = 0; i < nodes_.size(); i++) { - if (nodes_[i]->hasEvidence()) { - BpNode* v = static_cast (nodes_[i]); - addEvidence (v); - vector parents = cast (v->getParents()); - for (unsigned int i = 0; i < parents.size(); i++) { - if (!parents[i]->hasEvidence()) { - sendLambdaMessage (v, parents[i]); - } - } - vector childs = cast (v->getChilds()); - for (unsigned int i = 0; i < childs.size(); i++) { - sendPiMessage (v, childs[i]); - } - } - } - } else if (schedule_ == PARALLEL_SCHEDULE) { - BpNode::enableParallelSchedule(); - initializeSolver (queryVars); - for (unsigned int i = 0; i < nodes_.size(); i++) { - if (nodes_[i]->hasEvidence()) { - addEvidence (static_cast (nodes_[i])); - } - } - runIterativeBpSolver(); - } -} - - - -void -BpNetwork::printCurrentStatus (void) -{ - for (unsigned int i = 0; i < nodes_.size(); i++) { - printCurrentStatusOf (static_cast (nodes_[i])); - } -} - - - -void -BpNetwork::printCurrentStatusOf (BpNode* x) -{ - vector childs = cast (x->getChilds()); - vector domain = x->getDomain(); - - cout << left; - cout << setw (10) << "domain" ; - cout << setw (20) << "π(" + x->getVariableName() + ")" ; - cout << setw (20) << "λ(" + x->getVariableName() + ")" ; - cout << setw (16) << "belief" ; - cout << endl; - - cout << "--------------------------------" ; - cout << "--------------------------------" ; - cout << endl; - - double* piValues = x->getPiValues(); - double* lambdaValues = x->getLambdaValues(); - double* beliefs = x->getBeliefs(); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - cout << setw (10) << domain[xi]; - cout << setw (19) << piValues[xi]; - cout << setw (19) << lambdaValues[xi]; - cout.precision (PRECISION_); - cout << setw (16) << beliefs[xi]; - cout << endl; - } - cout << endl; - if (childs.size() > 0) { - string s = "(" + x->getVariableName() + ")" ; - for (unsigned int j = 0; j < childs.size(); j++) { - cout << setw (10) << "domain" ; - cout << setw (28) << "π" + childs[j]->getVariableName() + s; - cout << setw (28) << "λ" + childs[j]->getVariableName() + s; - cout << endl; - cout << "--------------------------------" ; - cout << "--------------------------------" ; - cout << endl; - for (int xi = 0; xi < x->getDomainSize(); xi++) { - cout << setw (10) << domain[xi]; - cout.precision (PRECISION_); - cout << setw (27) << x->getPiMessage(childs[j], xi); - cout.precision (PRECISION_); - cout << setw (27) << x->getLambdaMessage(childs[j], xi); - cout << endl; - } - cout << endl; - } - } -} - - - -void -BpNetwork::printBeliefs (void) -{ - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast (nodes_[i]); - vector domain = x->getDomain(); - cout << setw (20) << left << x->getVariableName() ; - cout << setw (26) << "belief" ; - cout << endl; - cout << "--------------------------------------" ; - cout << endl; - double* beliefs = x->getBeliefs(); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - cout << setw (20) << domain[xi]; - cout.precision (PRECISION_); - cout << setw (26) << beliefs[xi]; - cout << endl; - } - cout << endl; - } -} - - - -vector -BpNetwork::getBeliefs (void) -{ - return getBeliefs (queryNode_); -} - - - -vector -BpNetwork::getBeliefs (BpNode* x) -{ - double* beliefs = x->getBeliefs(); - vector beliefsVec; - for (int xi = 0; xi < x->getDomainSize(); xi++) { - beliefsVec.push_back (beliefs[xi]); - } - return beliefsVec; -} - - - -void -BpNetwork::initializeSolver (vector queryVars) -{ - if (DL_ >= 1) { - cout << "Initializing solver" << endl; - if (schedule_ == SEQUENTIAL_SCHEDULE) { - cout << "-> schedule = sequential" << endl; - } else { - cout << "-> schedule = parallel" << endl; - } - cout << "-> max iters = " << maxIter_ << endl; - cout << "-> stable threashold = " << stableThreashold_ << endl; - cout << "-> query vars = " ; - for (unsigned int i = 0; i < queryVars.size(); i++) { - cout << queryVars[i]->getVariableName() << " " ; - } - cout << endl; - } - - nIter_ = 0; - - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* node = static_cast (nodes_[i]); - node->allocateMemory(); - } - - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast (nodes_[i]); - - double* piValues = x->getPiValues(); - double* lambdaValues = x->getLambdaValues(); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - piValues[xi] = 1.0; - lambdaValues[xi] = 1.0; - } - - vector xChilds = cast (x->getChilds()); - for (unsigned int j = 0; j < xChilds.size(); j++) { - double* piMessages = x->getPiMessages (xChilds[j]); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - piMessages[xi] = 1.0; - //x->setPiMessage (xChilds[j], xi, 1.0); - } - } - - vector xParents = cast (x->getParents()); - for (unsigned int j = 0; j < xParents.size(); j++) { - double* lambdaMessages = xParents[j]->getLambdaMessages (x); - for (int xi = 0; xi < xParents[j]->getDomainSize(); xi++) { - lambdaMessages[xi] = 1.0; - //xParents[j]->setLambdaMessage (x, xi, 1.0); - } - } - } - - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast (nodes_[i]); - x->normalizeMessages(); - } - printCurrentStatus(); - - - vector roots = cast (getRootNodes()); - for (unsigned int i = 0; i < roots.size(); i++) { - double* params = roots[i]->getParameters(); - double* piValues = roots[i]->getPiValues(); - for (int ri = 0; ri < roots[i]->getDomainSize(); ri++) { - piValues[ri] = params[ri]; - } - } -} - - - -void -BpNetwork::addJunctionNode (vector queryVars) -{ - const string VAR_NAME = "_Jn"; - int nStates = 1; - vector parents; - vector domain; - for (unsigned int i = 0; i < queryVars.size(); i++) { - parents.push_back (queryVars[i]); - nStates *= queryVars[i]->getDomainSize(); - } - - for (int i = 0; i < nStates; i++) { - stringstream ss; - ss << "_jn" << i; - domain.push_back (ss.str()); // FIXME make domain optional - } - - int nParams = nStates * nStates; - double* params = new double [nParams]; - for (int i = 0; i < nParams; i++) { - int row = i / nStates; - int col = i % nStates; - if (row == col) { - params[i] = 1; - } else { - params[i] = 0; - } - } - addNode (VAR_NAME, parents, params, nParams, domain); - queryNode_ = static_cast (getNode (VAR_NAME)); - printNetwork(); -} - - - -void -BpNetwork::addEvidence (BpNode* v) -{ - if (DL_ >= 1) { - cout << "Adding evidence: node " ; - cout << "`" << v->getVariableName() << "' was instantiated as " ; - cout << "`" << v->getDomain()[v->getEvidence()] << "'" ; - cout << endl; - } - double* piValues = v->getPiValues(); - double* lambdaValues = v->getLambdaValues(); - for (int vi = 0; vi < v->getDomainSize(); vi++) { - if (vi == v->getEvidence()) { - piValues[vi] = 1.0; - lambdaValues[vi] = 1.0; - } else { - piValues[vi] = 0.0; - lambdaValues[vi] = 0.0; - } - } -} - - - -void -BpNetwork::runNeapolitanSolver (void) -{ - vector roots = cast (getRootNodes()); - for (unsigned int i = 0; i < roots.size(); i++) { - vector childs = cast (roots[i]->getChilds()); - for (unsigned int j = 0; j < childs.size(); j++) { - sendPiMessage (roots[i], static_cast (childs[j])); - } - } -} - - - -void -BpNetwork::sendPiMessage (BpNode* z, BpNode* x) -{ - nIter_ ++; - if (!(maxIter_ == -1 || nIter_ < maxIter_)) { - cout << "the maximum number of iterations was achieved, terminating..." ; - cout << endl; - return; - } - - if (DL_ >= 1) { - cout << "π message " << z->getVariableName(); - cout << " --> " << x->getVariableName() << endl; - } - - updatePiMessages(z, x); - - if (!x->hasEvidence()) { - updatePiValues (x); - vector xChilds = cast (x->getChilds()); - for (unsigned int i = 0; i < xChilds.size(); i++) { - sendPiMessage (x, xChilds[i]); - } - } - - bool isAllOnes = true; - double* lambdaValues = x->getLambdaValues(); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - if (lambdaValues[xi] != 1.0) { - isAllOnes = false; - break; - } - } - - if (!isAllOnes) { - vector xParents = cast (x->getParents()); - for (unsigned int i = 0; i < xParents.size(); i++) { - if (xParents[i] != z && !xParents[i]->hasEvidence()) { - sendLambdaMessage (x, xParents[i]); - } - } - } -} - - - -void -BpNetwork::sendLambdaMessage (BpNode* y, BpNode* x) -{ - nIter_ ++; - if (!(maxIter_ == -1 || nIter_ < maxIter_)) { - cout << "the maximum number of iterations was achieved, terminating..." ; - cout << endl; - return; - } - - if (DL_ >= 1) { - cout << "λ message " << y->getVariableName(); - cout << " --> " << x->getVariableName() << endl; - } - - updateLambdaMessages (x, y); - updateLambdaValues (x); - - vector xParents = cast (x->getParents()); - for (unsigned int i = 0; i < xParents.size(); i++) { - if (!xParents[i]->hasEvidence()) { - sendLambdaMessage (x, xParents[i]); - } - } - - vector xChilds = cast (x->getChilds()); - for (unsigned int i = 0; i < xChilds.size(); i++) { - if (xChilds[i] != y) { - sendPiMessage (x, xChilds[i]); - } - } -} - - - -void -BpNetwork::updatePiValues (BpNode* x) -{ - // π(Xi) - vector parents = cast (x->getParents()); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - stringstream calcs1; - stringstream calcs2; - if (DL_ >= 2) { - calcs1 << "π("<< x->getDomain()[xi] << ")" << endl << "= " ; - } - double sum = 0.0; - vector > constraints; - vector entries = x->getCptEntriesOfRow (xi); - for (unsigned int k = 0; k < entries.size(); k++) { - double prod = x->getProbability (entries[k]); - if (DL_ >= 2) { - if (k != 0) calcs1 << endl << "+ " ; - calcs1 << x->entryToString (entries[k]); - if (DL_ >= 3) { - (k == 0) ? calcs2 << "(" << prod : calcs2 << endl << "+ (" << prod; - } - } - vector insts = entries[k].getDomainInstantiations(); - for (unsigned int i = 0; i < parents.size(); i++) { - double value = parents[i]->getPiMessage (x, insts[i + 1]); - prod *= value; - if (DL_ >= 2) { - calcs1 << ".π" << x->getVariableName(); - calcs1 << "(" << parents[i]->getDomain()[insts[i + 1]] << ")"; - if (DL_ >= 3) calcs2 << "x" << value; - } - } - sum += prod; - if (DL_ >= 3) calcs2 << ")"; - } - x->setPiValue (xi, sum); - if (DL_ >= 2) { - cout << calcs1.str(); - if (DL_ >= 3) cout << endl << "= " << calcs2.str(); - cout << " = " << sum << endl; - } - } -} - - - -void -BpNetwork::updatePiMessages (BpNode* z, BpNode* x) -{ - // πX(Zi) - vector zChilds = cast (z->getChilds()); - for (int zi = 0; zi < z->getDomainSize(); zi++) { - stringstream calcs1; - stringstream calcs2; - if (DL_ >= 2) { - calcs1 << "π" << x->getVariableName(); - calcs1 << "(" << z->getDomain()[zi] << ") = " ; - } - double prod = z->getPiValue (zi); - if (DL_ >= 2) { - calcs1 << "π(" << z->getDomain()[zi] << ")" ; - if (DL_ >= 3) calcs2 << prod; - } - for (unsigned int i = 0; i < zChilds.size(); i++) { - if (zChilds[i] != x) { - double value = z->getLambdaMessage (zChilds[i], zi); - prod *= value; - if (DL_ >= 2) { - calcs1 << ".λ" << zChilds[i]->getVariableName(); - calcs1 << "(" << z->getDomain()[zi] + ")" ; - if (DL_ >= 3) calcs2 << " x " << value; - } - } - } - z->setPiMessage (x, zi, prod); - if (DL_ >= 2) { - cout << calcs1.str(); - if (DL_ >= 3) cout << " = " << calcs2.str(); - cout << " = " << prod << endl; - } - } -} - - - -void -BpNetwork::updateLambdaValues (BpNode* x) -{ - // λ(Xi) - vector childs = cast (x->getChilds()); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - stringstream calcs1; - stringstream calcs2; - if (DL_ >= 2) { - calcs1 << "λ" << "(" << x->getDomain()[xi] << ") = " ; - } - double prod = 1.0; - for (unsigned int i = 0; i < childs.size(); i++) { - double val = x->getLambdaMessage (childs[i], xi); - prod *= val; - if (DL_ >= 2) { - if (i != 0) calcs1 << "." ; - calcs1 << "λ" << childs[i]->getVariableName(); - calcs1 << "(" << x->getDomain()[xi] + ")" ; - if (DL_ >= 3) (i == 0) ? calcs2 << val : calcs2 << " x " << val; - } - } - x->setLambdaValue (xi, prod); - if (DL_ >= 2) { - cout << calcs1.str(); - if (childs.size() == 0) { - cout << 1 << endl; - } else { - if (DL_ >= 3) cout << " = " << calcs2.str(); - cout << " = " << prod << endl; - } - } - } -} - - - -void -BpNetwork::updateLambdaMessages (BpNode* x, BpNode* y) -{ - // λY(Xi) - int parentIndex = y->getIndexOfParent (x) + 1; - vector yParents = cast (y->getParents()); - for (int xi = 0; xi < x->getDomainSize(); xi++) { - stringstream calcs1; - stringstream calcs2; - if (DL_ >= 2) { - calcs1 << "λ" << y->getVariableName() ; - calcs1 << "(" << x->getDomain()[xi] << ")" << endl << "= " ; - } - double outer_sum = 0.0; - for (int yi = 0; yi < y->getDomainSize(); yi++) { - if (DL_ >= 2) { - (yi == 0) ? calcs1 << "[" : calcs1 << endl << "+ [" ; - if (DL_ >= 3) { - (yi == 0) ? calcs2 << "[" : calcs2 << endl << "+ [" ; - } - } - double inner_sum = 0.0; - vector > constraints; - constraints.push_back (make_pair (0, yi)); - constraints.push_back (make_pair (parentIndex, xi)); - vector entries = y->getCptEntries (constraints); - for (unsigned int k = 0; k < entries.size(); k++) { - double prod = y->getProbability (entries[k]); - if (DL_ >= 2) { - if (k != 0) calcs1 << " + " ; - calcs1 << y->entryToString (entries[k]); - if (DL_ >= 3) { - (k == 0) ? calcs2 << "(" << prod : calcs2 << " + (" << prod; - } - } - vector insts = entries[k].getDomainInstantiations(); - for (unsigned int i = 0; i < yParents.size(); i++) { - if (yParents[i] != x) { - double val = yParents[i]->getPiMessage (y, insts[i + 1]); - prod *= val; - if (DL_ >= 2) { - calcs1 << ".π" << y->getVariableName(); - calcs1 << "(" << yParents[i]->getDomain()[insts[i + 1]] << ")" ; - if (DL_ >= 3) calcs2 << "x" << val; - } - - } - } - inner_sum += prod; - if (DL_ >= 3) { - calcs2 << ")" ; - } - } - outer_sum += inner_sum * y->getLambdaValue (yi); - if (DL_ >= 2) { - calcs1 << "].λ(" << y->getDomain()[yi] << ")"; - if (DL_ >= 3) calcs2 << "]x" << y->getLambdaValue (yi); - } - } - x->setLambdaMessage (y, xi, outer_sum); - if (DL_ >= 2) { - cout << calcs1.str(); - if (DL_ >= 3) cout << endl << "= " << calcs2.str(); - cout << " = " << outer_sum << endl; - } - } -} - - - -void -BpNetwork::runIterativeBpSolver() -{ - int nIter = 0; - maxIter_ = 100; - bool converged = false; - while (nIter < maxIter_ && !converged) { - if (DL_ >= 1) { - cout << endl << endl; - cout << "****************************************" ; - cout << "****************************************" ; - cout << endl; - cout << " Iteration " << nIter + 1 << endl; - cout << "****************************************" ; - cout << "****************************************" ; - } - - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast(nodes_[i]); - vector xParents = cast (x->getParents()); - for (unsigned int j = 0; j < xParents.size(); j++) { - //if (!xParents[j]->hasEvidence()) { - if (DL_ >= 1) { - cout << endl << "λ message " << x->getVariableName(); - cout << " --> " << xParents[j]->getVariableName() << endl; - } - updateLambdaMessages (xParents[j], x); - //} - } - } - - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast(nodes_[i]); - vector xChilds = cast (x->getChilds()); - for (unsigned int j = 0; j < xChilds.size(); j++) { - if (DL_ >= 1) { - cout << endl << "π message " << x->getVariableName(); - cout << " --> " << xChilds[j]->getVariableName() << endl; - } - updatePiMessages (x, xChilds[j]); - } - } - - /* - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast(nodes_[i]); - vector xChilds = cast (x->getChilds()); - for (unsigned int j = 0; j < xChilds.size(); j++) { - if (DL_ >= 1) { - cout << "π message " << x->getVariableName(); - cout << " --> " << xChilds[j]->getVariableName() << endl; - } - updatePiMessages (x, xChilds[j]); - } - vector xParents = cast (x->getParents()); - for (unsigned int j = 0; j < xParents.size(); j++) { - //if (!xParents[j]->hasEvidence()) { - if (DL_ >= 1) { - cout << "λ message " << x->getVariableName(); - cout << " --> " << xParents[j]->getVariableName() << endl; - } - updateLambdaMessages (xParents[j], x); - //} - } - } - */ - - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast (nodes_[i]); - //cout << endl << "SWAPING MESSAGES FOR " << x->getVariableName() << ":" ; - //cout << endl << endl; - //printCurrentStatusOf (x); - x->swapMessages(); - x->normalizeMessages(); - //cout << endl << "messages swaped " << endl; - //printCurrentStatusOf (x); - } - - converged = true; - for (unsigned int i = 0; i < nodes_.size(); i++) { - BpNode* x = static_cast(nodes_[i]); - if (DL_ >= 1) { - cout << endl << "var " << x->getVariableName() << ":" << endl; - } - //if (!x->hasEvidence()) { - updatePiValues (x); - updateLambdaValues (x); - double change = x->getBeliefChange(); - if (DL_ >= 1) { - cout << "belief change = " << change << endl; - } - if (change > stableThreashold_) { - converged = false; - } - //} - } - - if (converged) { - // converged = false; - } - if (DL_ >= 2) { - cout << endl; - printCurrentStatus(); - } - nIter++; - } - - if (DL_ >= 1) { - cout << endl; - if (converged) { - cout << "Iterative belief propagation converged in " ; - cout << nIter << " iterations" << endl; - } else { - cout << "Iterative belief propagation converged didn't converge" ; - cout << endl; - } - if (DL_ == 1) { - cout << endl; - printBeliefs(); - } - cout << endl; - } -} - - - -void -BpNetwork::addNode (string varName, - vector parents, - int evidence, - int distId) -{ - for (unsigned int i = 0; i < dists_.size(); i++) { - if (dists_[i]->id == distId) { - BpNode* node = new BpNode (varName, parents, dists_[i], evidence); - nodes_.push_back (node); - break; - } - } -} - - - -void -BpNetwork::addNode (string varName, - vector parents, - double* params, - int nParams, - vector domain) -{ - Distribution* dist = new Distribution (params, nParams, domain); - BpNode* node = new BpNode (varName, parents, dist); - dists_.push_back (dist); - nodes_.push_back (node); -} - - - -vector -BpNetwork::cast (vector nodes) -{ - vector castedNodes (nodes.size()); - for (unsigned int i = 0; i < nodes.size(); i++) { - castedNodes[i] = static_cast (nodes[i]); - } - return castedNodes; -} - diff --git a/packages/CLPBN/clpbn/bp/BpNetwork.h b/packages/CLPBN/clpbn/bp/BpNetwork.h deleted file mode 100644 index a37b079af..000000000 --- a/packages/CLPBN/clpbn/bp/BpNetwork.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef BP_BP_NETWORK_H -#define BP_BP_NETWORK_H - -#include -#include - -#include "BayesianNetwork.h" - -using namespace std; - -class BpNode; - -enum Schedule -{ - SEQUENTIAL_SCHEDULE, - PARALLEL_SCHEDULE -}; - -class BpNetwork : public BayesianNetwork -{ - public: - // constructs - BpNetwork (void); - // destruct - ~BpNetwork (void); - // methods - void setSolverParameters (Schedule, int, double); - void runSolver (BayesianNode* queryVar); - void runSolver (vector); - void printCurrentStatus (void); - void printCurrentStatusOf (BpNode*); - void printBeliefs (void); - vector getBeliefs (void); - vector getBeliefs (BpNode*); - - private: - BpNetwork (const BpNetwork&); // disallow copy - void operator= (const BpNetwork&); // disallow assign - // methods - void initializeSolver (vector); - void addJunctionNode (vector); - void addEvidence (BpNode*); - void runNeapolitanSolver (void); - void sendLambdaMessage (BpNode*, BpNode*); - void sendPiMessage (BpNode*, BpNode*); - void updatePiValues (BpNode*); - void updatePiMessages (BpNode*, BpNode*); - void updateLambdaValues (BpNode*); - void updateLambdaMessages (BpNode*, BpNode*); - void runIterativeBpSolver (void); - void addNode (string, vector, int, int); - void addNode (string, vector, - double*, int, vector); - vector cast (vector); - // members - Schedule schedule_; - int nIter_; - int maxIter_; - double stableThreashold_; - BpNode* queryNode_; - static const int DL_ = 3; - static const int PRECISION_ = 10; -}; - -#endif // BP_BP_NETWORK_H - diff --git a/packages/CLPBN/clpbn/bp/BpNode.cpp b/packages/CLPBN/clpbn/bp/BpNode.cpp deleted file mode 100644 index 4fd52f95c..000000000 --- a/packages/CLPBN/clpbn/bp/BpNode.cpp +++ /dev/null @@ -1,250 +0,0 @@ -#include -#include -#include - -#include "BpNode.h" - -bool BpNode::calculateMessageResidual_ = true; - - -BpNode::BpNode (BayesNode* node) -{ - ds_ = node->getDomainSize(); - const NodeSet& childs = node->getChilds(); - piVals_.resize (ds_, 1); - ldVals_.resize (ds_, 1); - if (calculateMessageResidual_) { - piResiduals_.resize (childs.size(), 0.0); - ldResiduals_.resize (childs.size(), 0.0); - } - childs_ = &childs; - for (unsigned i = 0; i < childs.size(); i++) { - //indexMap_.insert (make_pair (childs[i]->getVarId(), i)); - currPiMsgs_.push_back (ParamSet (ds_, 1)); - currLdMsgs_.push_back (ParamSet (ds_, 1)); - nextPiMsgs_.push_back (ParamSet (ds_, 1)); - nextLdMsgs_.push_back (ParamSet (ds_, 1)); - } -} - - - -ParamSet -BpNode::getBeliefs (void) const -{ - double sum = 0.0; - ParamSet beliefs (ds_); - for (int xi = 0; xi < ds_; xi++) { - double prod = piVals_[xi] * ldVals_[xi]; - beliefs[xi] = prod; - sum += prod; - } - assert (sum); - //normalize the beliefs - for (int xi = 0; xi < ds_; xi++) { - beliefs[xi] /= sum; - } - return beliefs; -} - - - -double -BpNode::getPiValue (int idx) const -{ - assert (idx >=0 && idx < ds_); - return piVals_[idx]; -} - - - -void -BpNode::setPiValue (int idx, double value) -{ - assert (idx >=0 && idx < ds_); - piVals_[idx] = value; -} - - - -double -BpNode::getLambdaValue (int idx) const -{ - assert (idx >=0 && idx < ds_); - return ldVals_[idx]; -} - - - -void -BpNode::setLambdaValue (int idx, double value) -{ - assert (idx >=0 && idx < ds_); - ldVals_[idx] = value; -} - - - -ParamSet& -BpNode::getPiValues (void) -{ - return piVals_; -} - - - -ParamSet& -BpNode::getLambdaValues (void) -{ - return ldVals_; -} - - - -double -BpNode::getPiMessageValue (const BayesNode* destination, int idx) const -{ - assert (idx >=0 && idx < ds_); - return currPiMsgs_[getIndex(destination)][idx]; -} - - - -double -BpNode::getLambdaMessageValue (const BayesNode* source, int idx) const -{ - assert (idx >=0 && idx < ds_); - return currLdMsgs_[getIndex(source)][idx]; -} - - - -const ParamSet& -BpNode::getPiMessage (const BayesNode* destination) const -{ - return currPiMsgs_[getIndex(destination)]; -} - - - -const ParamSet& -BpNode::getLambdaMessage (const BayesNode* source) const -{ - return currLdMsgs_[getIndex(source)]; -} - - - -ParamSet& -BpNode::piNextMessageReference (const BayesNode* destination) -{ - return nextPiMsgs_[getIndex(destination)]; -} - - - -ParamSet& -BpNode::lambdaNextMessageReference (const BayesNode* source) -{ - return nextLdMsgs_[getIndex(source)]; -} - - - -void -BpNode::updatePiMessage (const BayesNode* destination) -{ - int idx = getIndex (destination); - currPiMsgs_[idx] = nextPiMsgs_[idx]; - Util::normalize (currPiMsgs_[idx]); -} - - - -void -BpNode::updateLambdaMessage (const BayesNode* source) -{ - int idx = getIndex (source); - currLdMsgs_[idx] = nextLdMsgs_[idx]; - Util::normalize (currLdMsgs_[idx]); -} - - - -double -BpNode::getBeliefChange (void) -{ - double change = 0.0; - if (oldBeliefs_.size() == 0) { - oldBeliefs_ = getBeliefs(); - change = 9999999999.0; - } else { - ParamSet currentBeliefs = getBeliefs(); - for (int xi = 0; xi < ds_; xi++) { - change += abs (currentBeliefs[xi] - oldBeliefs_[xi]); - } - oldBeliefs_ = currentBeliefs; - } - return change; -} - - - -void -BpNode::updatePiResidual (const BayesNode* destination) -{ - int idx = getIndex (destination); - Util::normalize (nextPiMsgs_[idx]); - //piResiduals_[idx] = Util::getL1dist ( - // currPiMsgs_[idx], nextPiMsgs_[idx]); - piResiduals_[idx] = Util::getMaxNorm ( - currPiMsgs_[idx], nextPiMsgs_[idx]); -} - - - -void -BpNode::updateLambdaResidual (const BayesNode* source) -{ - int idx = getIndex (source); - Util::normalize (nextLdMsgs_[idx]); - //ldResiduals_[idx] = Util::getL1dist ( - // currLdMsgs_[idx], nextLdMsgs_[idx]); - ldResiduals_[idx] = Util::getMaxNorm ( - currLdMsgs_[idx], nextLdMsgs_[idx]); -} - - - -void -BpNode::clearPiResidual (const BayesNode* destination) -{ - piResiduals_[getIndex(destination)] = 0; -} - - - -void -BpNode::clearLambdaResidual (const BayesNode* source) -{ - ldResiduals_[getIndex(source)] = 0; -} - - - -bool -BpNode::hasReceivedChildInfluence (void) const -{ - // if all lambda values are equal, then neither - // this node neither its descendents have evidence, - // we can use this to don't send lambda messages his parents - bool childInfluenced = false; - for (int xi = 1; xi < ds_; xi++) { - if (ldVals_[xi] != ldVals_[0]) { - childInfluenced = true; - break; - } - } - return childInfluenced; -} - diff --git a/packages/CLPBN/clpbn/bp/BpNode.h b/packages/CLPBN/clpbn/bp/BpNode.h deleted file mode 100644 index 2b84a298d..000000000 --- a/packages/CLPBN/clpbn/bp/BpNode.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef BP_BPNODE_H -#define BP_BPNODE_H - -#include -#include -#include -#include - -#include "BayesNode.h" -#include "Shared.h" - -using namespace std; - -class BpNode -{ - public: - BpNode (int); - BpNode (BayesNode*); - - ParamSet getBeliefs (void) const; - double getPiValue (int) const; - void setPiValue (int, double); - double getLambdaValue (int) const; - void setLambdaValue (int, double); - ParamSet& getPiValues (void); - ParamSet& getLambdaValues (void); - double getPiMessageValue (const BayesNode*, int) const; - double getLambdaMessageValue (const BayesNode*, int) const; - const ParamSet& getPiMessage (const BayesNode*) const; - const ParamSet& getLambdaMessage (const BayesNode*) const; - ParamSet& piNextMessageReference (const BayesNode*); - ParamSet& lambdaNextMessageReference (const BayesNode*); - void updatePiMessage (const BayesNode*); - void updateLambdaMessage (const BayesNode*); - double getBeliefChange (void); - void updatePiResidual (const BayesNode*); - void updateLambdaResidual (const BayesNode*); - void clearPiResidual (const BayesNode*); - void clearLambdaResidual (const BayesNode*); - bool hasReceivedChildInfluence (void) const; - // inlines - double getPiResidual (const BayesNode*); - double getLambdaResidual (const BayesNode*); - int getIndex (const BayesNode*) const; - - private: - DISALLOW_COPY_AND_ASSIGN (BpNode); - - IndexMap indexMap_; - ParamSet piVals_; // pi values - ParamSet ldVals_; // lambda values - vector currPiMsgs_; // current pi messages - vector currLdMsgs_; // current lambda messages - vector nextPiMsgs_; - vector nextLdMsgs_; - ParamSet oldBeliefs_; - ParamSet piResiduals_; - ParamSet ldResiduals_; - int ds_; - const NodeSet* childs_; - static bool calculateMessageResidual_; -// static const double MAX_CHANGE_ = 10000000.0; -}; - - - -inline double -BpNode::getPiResidual (const BayesNode* destination) -{ - return piResiduals_[getIndex(destination)]; -} - - -inline double -BpNode::getLambdaResidual (const BayesNode* source) -{ - return ldResiduals_[getIndex(source)]; -} - - - -inline int -BpNode::getIndex (const BayesNode* node) const -{ - assert (node); - //assert (indexMap_.find(node->getVarId()) != indexMap_.end()); - //return indexMap_.find(node->getVarId())->second; - for (unsigned i = 0; childs_->size(); i++) { - if ((*childs_)[i]->getVarId() == node->getVarId()) { - return i; - } - } - assert (false); - return -1; -} - - -#endif - diff --git a/packages/CLPBN/clpbn/bp/CountingBP.cpp b/packages/CLPBN/clpbn/bp/CountingBP.cpp deleted file mode 100644 index 645c61418..000000000 --- a/packages/CLPBN/clpbn/bp/CountingBP.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include "CountingBP.h" - - -CountingBP::~CountingBP (void) -{ - delete lfg_; - delete fg_; - for (unsigned i = 0; i < links_.size(); i++) { - delete links_[i]; - } - links_.clear(); -} - - - -ParamSet -CountingBP::getPosterioriOf (Vid vid) const -{ - FgVarNode* var = lfg_->getEquivalentVariable (vid); - ParamSet probs; - - if (var->hasEvidence()) { - probs.resize (var->getDomainSize(), 0.0); - probs[var->getEvidence()] = 1.0; - } else { - probs.resize (var->getDomainSize(), 1.0); - CLinkSet links = varsI_[var->getIndex()]->getLinks(); - for (unsigned i = 0; i < links.size(); i++) { - ParamSet msg = links[i]->getMessage(); - CountingBPLink* l = static_cast (links[i]); - Util::pow (msg, l->getNumberOfEdges()); - for (unsigned j = 0; j < msg.size(); j++) { - probs[j] *= msg[j]; - } - } - Util::normalize (probs); - } - return probs; -} - - - -void -CountingBP::initializeSolver (void) -{ - lfg_ = new LiftedFG (*fg_); - unsigned nUncVars = fg_->getFgVarNodes().size(); - unsigned nUncFactors = fg_->getFactors().size(); - CFgVarSet vars = fg_->getFgVarNodes(); - unsigned nNeighborLessVars = 0; - for (unsigned i = 0; i < vars.size(); i++) { - CFactorSet factors = vars[i]->getFactors(); - if (factors.size() == 1 && factors[0]->getFgVarNodes().size() == 1) { - nNeighborLessVars ++; - } - } - // cout << "UNCOMPRESSED FACTOR GRAPH" << endl; - // fg_->printGraphicalModel(); - fg_->exportToDotFormat ("uncompress.dot"); - - FactorGraph *temp; - temp = fg_; - fg_ = lfg_->getCompressedFactorGraph(); - unsigned nCompVars = fg_->getFgVarNodes().size(); - unsigned nCompFactors = fg_->getFactors().size(); - - Statistics::updateCompressingStats (nUncVars, - nUncFactors, - nCompVars, - nCompFactors, - nNeighborLessVars); - - cout << "COMPRESSED FACTOR GRAPH" << endl; - fg_->printGraphicalModel(); - //fg_->exportToDotFormat ("compress.dot"); - - SPSolver::initializeSolver(); -} - - - -void -CountingBP::createLinks (void) -{ - const FactorClusterSet fcs = lfg_->getFactorClusters(); - for (unsigned i = 0; i < fcs.size(); i++) { - const VarClusterSet vcs = fcs[i]->getVarClusters(); - for (unsigned j = 0; j < vcs.size(); j++) { - unsigned c = lfg_->getGroundEdgeCount (fcs[i], vcs[j]); - links_.push_back ( - new CountingBPLink (fcs[i]->getRepresentativeFactor(), - vcs[j]->getRepresentativeVariable(), c)); - //cout << (links_.back())->toString() << " edge count =" << c << endl; - } - } - return; -} - - - -void -CountingBP::deleteJunction (Factor* f, FgVarNode*) -{ - f->freeDistribution(); -} - - - -void -CountingBP::maxResidualSchedule (void) -{ - if (nIter_ == 1) { - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->setNextMessage (getFactor2VarMsg (links_[i])); - SortedOrder::iterator it = sortedOrder_.insert (links_[i]); - linkMap_.insert (make_pair (links_[i], it)); - if (DL >= 2 && DL < 5) { - cout << "calculating " << links_[i]->toString() << endl; - } - } - return; - } - - for (unsigned c = 0; c < links_.size(); c++) { - if (DL >= 2) { - cout << endl << "current residuals:" << endl; - for (SortedOrder::iterator it = sortedOrder_.begin(); - it != sortedOrder_.end(); it ++) { - cout << " " << setw (30) << left << (*it)->toString(); - cout << "residual = " << (*it)->getResidual() << endl; - } - } - - SortedOrder::iterator it = sortedOrder_.begin(); - Link* link = *it; - if (DL >= 2) { - cout << "updating " << (*sortedOrder_.begin())->toString() << endl; - } - if (link->getResidual() < SolverOptions::accuracy) { - return; - } - link->updateMessage(); - link->clearResidual(); - sortedOrder_.erase (it); - linkMap_.find (link)->second = sortedOrder_.insert (link); - - // update the messages that depend on message source --> destin - CFactorSet factorNeighbors = link->getVariable()->getFactors(); - for (unsigned i = 0; i < factorNeighbors.size(); i++) { - CLinkSet links = factorsI_[factorNeighbors[i]->getIndex()]->getLinks(); - for (unsigned j = 0; j < links.size(); j++) { - if (links[j]->getVariable() != link->getVariable()) { //FIXMEFIXME - if (DL >= 2 && DL < 5) { - cout << " calculating " << links[j]->toString() << endl; - } - links[j]->setNextMessage (getFactor2VarMsg (links[j])); - LinkMap::iterator iter = linkMap_.find (links[j]); - sortedOrder_.erase (iter->second); - iter->second = sortedOrder_.insert (links[j]); - } - } - } - } -} - - - -ParamSet -CountingBP::getVar2FactorMsg (const Link* link) const -{ - const FgVarNode* src = link->getVariable(); - const Factor* dest = link->getFactor(); - ParamSet msg; - if (src->hasEvidence()) { - cout << "has evidence" << endl; - msg.resize (src->getDomainSize(), 0.0); - msg[src->getEvidence()] = link->getMessage()[src->getEvidence()]; - cout << "-> " << link->getVariable()->getLabel() << " " << link->getFactor()->getLabel() << endl; - cout << "-> p2s " << Util::parametersToString (msg) << endl; - } else { - msg = link->getMessage(); - } - const CountingBPLink* l = static_cast (link); - Util::pow (msg, l->getNumberOfEdges() - 1); - CLinkSet links = varsI_[src->getIndex()]->getLinks(); - for (unsigned i = 0; i < links.size(); i++) { - if (links[i]->getFactor() != dest) { - ParamSet msgFromFactor = links[i]->getMessage(); - CountingBPLink* l = static_cast (links[i]); - Util::pow (msgFromFactor, l->getNumberOfEdges()); - for (unsigned j = 0; j < msgFromFactor.size(); j++) { - msg[j] *= msgFromFactor[j]; - } - } - } - return msg; -} - diff --git a/packages/CLPBN/clpbn/bp/CountingBP.h b/packages/CLPBN/clpbn/bp/CountingBP.h deleted file mode 100644 index 540817ba0..000000000 --- a/packages/CLPBN/clpbn/bp/CountingBP.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef BP_COUNTING_BP_H -#define BP_COUNTING_BP_H - -#include "SPSolver.h" -#include "LiftedFG.h" - -class Factor; -class FgVarNode; - -class CountingBPLink : public Link -{ - public: - CountingBPLink (Factor* f, FgVarNode* v, unsigned c) : Link (f, v) - { - edgeCount_ = c; - } - - unsigned getNumberOfEdges (void) const { return edgeCount_; } - - private: - unsigned edgeCount_; -}; - - -class CountingBP : public SPSolver -{ - public: - CountingBP (FactorGraph& fg) : SPSolver (fg) { } - ~CountingBP (void); - - ParamSet getPosterioriOf (Vid) const; - - private: - void initializeSolver (void); - void createLinks (void); - void deleteJunction (Factor*, FgVarNode*); - - void maxResidualSchedule (void); - ParamSet getVar2FactorMsg (const Link*) const; - - LiftedFG* lfg_; -}; - -#endif // BP_COUNTING_BP_H - diff --git a/packages/CLPBN/clpbn/bp/Distribution.cpp b/packages/CLPBN/clpbn/bp/Distribution.cpp deleted file mode 100644 index 309d8b73e..000000000 --- a/packages/CLPBN/clpbn/bp/Distribution.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include - -#include - -Distribution::Distribution (int id, - double* params, - int nParams, - vector domain) -{ - this->id = id; - this->params = params; - this->nParams = nParams; - this->domain = domain; -} - - -Distribution::Distribution (double* params, - int nParams, - vector domain) -{ - this->id = -1; - this->params = params; - this->nParams = nParams; - this->domain = domain; -} - - - -/* -Distribution::~Distribution() -{ - delete params; - for (unsigned int i = 0; i < cptEntries.size(); i++) { - delete cptEntries[i]; - } -} -*/ - - diff --git a/packages/CLPBN/clpbn/bp/FgVarNode.h b/packages/CLPBN/clpbn/bp/FgVarNode.h deleted file mode 100644 index e46c88f57..000000000 --- a/packages/CLPBN/clpbn/bp/FgVarNode.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BP_FG_VAR_NODE_H -#define BP_FG_VAR_NODE_H - -#include - -#include "Variable.h" -#include "Shared.h" - -using namespace std; - -class Factor; - -class FgVarNode : public Variable -{ - public: - FgVarNode (unsigned vid, unsigned dsize) : Variable (vid, dsize) { } - FgVarNode (const Variable* v) : Variable (v) { } - - void addFactor (Factor* f) { factors_.push_back (f); } - CFactorSet getFactors (void) const { return factors_; } - - void removeFactor (const Factor* f) - { - if (factors_[factors_.size() -1] == f) { - factors_.pop_back(); - } else { - for (unsigned i = 0; i < factors_.size(); i++) { - if (factors_[i] == f) { - factors_.erase (factors_.begin() + i); - return; - } - } - assert (false); - } - } - - private: - DISALLOW_COPY_AND_ASSIGN (FgVarNode); - // members - FactorSet factors_; -}; - -#endif // BP_FG_VAR_NODE_H diff --git a/packages/CLPBN/clpbn/bp/LiftedFG.cpp b/packages/CLPBN/clpbn/bp/LiftedFG.cpp deleted file mode 100644 index add8610cc..000000000 --- a/packages/CLPBN/clpbn/bp/LiftedFG.cpp +++ /dev/null @@ -1,278 +0,0 @@ - -#include "LiftedFG.h" -#include "FgVarNode.h" -#include "Factor.h" -#include "Distribution.h" - -LiftedFG::LiftedFG (const FactorGraph& fg) -{ - groundFg_ = &fg; - freeColor_ = 0; - - const FgVarSet& varNodes = fg.getFgVarNodes(); - const FactorSet& factors = fg.getFactors(); - varColors_.resize (varNodes.size()); - factorColors_.resize (factors.size()); - for (unsigned i = 0; i < factors.size(); i++) { - factors[i]->setIndex (i); - } - - // create the initial variable colors - VarColorMap colorMap; - for (unsigned i = 0; i < varNodes.size(); i++) { - unsigned dsize = varNodes[i]->getDomainSize(); - VarColorMap::iterator it = colorMap.find (dsize); - if (it == colorMap.end()) { - it = colorMap.insert (make_pair ( - dsize, vector (dsize + 1,-1))).first; - } - unsigned idx; - if (varNodes[i]->hasEvidence()) { - idx = varNodes[i]->getEvidence(); - } else { - idx = dsize; - } - vector& stateColors = it->second; - if (stateColors[idx] == -1) { - stateColors[idx] = getFreeColor(); - } - setColor (varNodes[i], stateColors[idx]); - } - - // create the initial factor colors - DistColorMap distColors; - for (unsigned i = 0; i < factors.size(); i++) { - Distribution* dist = factors[i]->getDistribution(); - DistColorMap::iterator it = distColors.find (dist); - if (it == distColors.end()) { - it = distColors.insert (make_pair (dist, getFreeColor())).first; - } - setColor (factors[i], it->second); - } - - VarSignMap varGroups; - FactorSignMap factorGroups; - bool groupsHaveChanged = true; - unsigned nIter = 0; - while (groupsHaveChanged || nIter == 1) { - nIter ++; - if (Statistics::numCreatedNets == 4) { - cout << "--------------------------------------------" << endl; - cout << "Iteration " << nIter << endl; - cout << "--------------------------------------------" << endl; - } - - unsigned prevFactorGroupsSize = factorGroups.size(); - factorGroups.clear(); - // set a new color to the factors with the same signature - for (unsigned i = 0; i < factors.size(); i++) { - const string& signatureId = getSignatureId (factors[i]); - // cout << factors[i]->getLabel() << " signature: " ; - // cout<< signatureId << endl; - FactorSignMap::iterator it = factorGroups.find (signatureId); - if (it == factorGroups.end()) { - it = factorGroups.insert (make_pair (signatureId, FactorSet())).first; - } - it->second.push_back (factors[i]); - } - if (nIter > 0) - for (FactorSignMap::iterator it = factorGroups.begin(); - it != factorGroups.end(); it++) { - Color newColor = getFreeColor(); - FactorSet& groupMembers = it->second; - for (unsigned i = 0; i < groupMembers.size(); i++) { - setColor (groupMembers[i], newColor); - } - } - - // set a new color to the variables with the same signature - unsigned prevVarGroupsSize = varGroups.size(); - varGroups.clear(); - for (unsigned i = 0; i < varNodes.size(); i++) { - const string& signatureId = getSignatureId (varNodes[i]); - VarSignMap::iterator it = varGroups.find (signatureId); - // cout << varNodes[i]->getLabel() << " signature: " ; - // cout << signatureId << endl; - if (it == varGroups.end()) { - it = varGroups.insert (make_pair (signatureId, FgVarSet())).first; - } - it->second.push_back (varNodes[i]); - } - if (nIter > 0) - for (VarSignMap::iterator it = varGroups.begin(); - it != varGroups.end(); it++) { - Color newColor = getFreeColor(); - FgVarSet& groupMembers = it->second; - for (unsigned i = 0; i < groupMembers.size(); i++) { - setColor (groupMembers[i], newColor); - } - } - - //if (nIter >= 3) cout << "bigger than three: " << nIter << endl; - groupsHaveChanged = prevVarGroupsSize != varGroups.size() - || prevFactorGroupsSize != factorGroups.size(); - } - - printGroups (varGroups, factorGroups); - for (VarSignMap::iterator it = varGroups.begin(); - it != varGroups.end(); it++) { - CFgVarSet vars = it->second; - VarCluster* vc = new VarCluster (vars); - for (unsigned i = 0; i < vars.size(); i++) { - vid2VarCluster_.insert (make_pair (vars[i]->getVarId(), vc)); - } - varClusters_.push_back (vc); - } - - for (FactorSignMap::iterator it = factorGroups.begin(); - it != factorGroups.end(); it++) { - VarClusterSet varClusters; - Factor* groundFactor = it->second[0]; - FgVarSet groundVars = groundFactor->getFgVarNodes(); - for (unsigned i = 0; i < groundVars.size(); i++) { - Vid vid = groundVars[i]->getVarId(); - varClusters.push_back (vid2VarCluster_.find (vid)->second); - } - factorClusters_.push_back (new FactorCluster (it->second, varClusters)); - } -} - - - -LiftedFG::~LiftedFG (void) -{ - for (unsigned i = 0; i < varClusters_.size(); i++) { - delete varClusters_[i]; - } - for (unsigned i = 0; i < factorClusters_.size(); i++) { - delete factorClusters_[i]; - } -} - - - -string -LiftedFG::getSignatureId (FgVarNode* var) const -{ - stringstream ss; - CFactorSet myFactors = var->getFactors(); - ss << myFactors.size(); - for (unsigned i = 0; i < myFactors.size(); i++) { - ss << "." << getColor (myFactors[i]); - ss << "." << myFactors[i]->getIndexOf(var); - } - ss << "." << getColor (var); - return ss.str(); -} - - - -string -LiftedFG::getSignatureId (Factor* factor) const -{ - stringstream ss; - CFgVarSet myVars = factor->getFgVarNodes(); - ss << myVars.size(); - for (unsigned i = 0; i < myVars.size(); i++) { - ss << "." << getColor (myVars[i]); - } - ss << "." << getColor (factor); - return ss.str(); -} - - - -FactorGraph* -LiftedFG::getCompressedFactorGraph (void) -{ - FactorGraph* fg = new FactorGraph(); - for (unsigned i = 0; i < varClusters_.size(); i++) { - FgVarNode* var = varClusters_[i]->getGroundFgVarNodes()[0]; - FgVarNode* newVar = new FgVarNode (var); - newVar->setIndex (i); - varClusters_[i]->setRepresentativeVariable (newVar); - fg->addVariable (newVar); - } - - for (unsigned i = 0; i < factorClusters_.size(); i++) { - FgVarSet myGroundVars; - const VarClusterSet& myVarClusters = factorClusters_[i]->getVarClusters(); - for (unsigned j = 0; j < myVarClusters.size(); j++) { - myGroundVars.push_back (myVarClusters[j]->getRepresentativeVariable()); - } - Factor* newFactor = new Factor (myGroundVars, - factorClusters_[i]->getGroundFactors()[0]->getDistribution()); - factorClusters_[i]->setRepresentativeFactor (newFactor); - fg->addFactor (newFactor); - } - return fg; -} - - - -unsigned -LiftedFG::getGroundEdgeCount (FactorCluster* fc, VarCluster* vc) const -{ - CFactorSet clusterGroundFactors = fc->getGroundFactors(); - FgVarNode* var = vc->getGroundFgVarNodes()[0]; - unsigned count = 0; - for (unsigned i = 0; i < clusterGroundFactors.size(); i++) { - if (clusterGroundFactors[i]->getIndexOf (var) != -1) { - count ++; - } - } - /* - CFgVarSet vars = vc->getGroundFgVarNodes(); - for (unsigned i = 1; i < vars.size(); i++) { - FgVarNode* var = vc->getGroundFgVarNodes()[i]; - unsigned count2 = 0; - for (unsigned i = 0; i < clusterGroundFactors.size(); i++) { - if (clusterGroundFactors[i]->getIndexOf (var) != -1) { - count2 ++; - } - } - if (count != count2) { cout << "oops!" << endl; abort(); } - } - */ - return count; -} - - - -void -LiftedFG::printGroups (const VarSignMap& varGroups, - const FactorSignMap& factorGroups) const -{ - cout << "variable groups:" << endl; - unsigned count = 0; - for (VarSignMap::const_iterator it = varGroups.begin(); - it != varGroups.end(); it++) { - const FgVarSet& groupMembers = it->second; - if (groupMembers.size() > 0) { - cout << ++count << ": " ; - //if (groupMembers.size() > 1) { - for (unsigned i = 0; i < groupMembers.size(); i++) { - cout << groupMembers[i]->getLabel() << " " ; - } - //} - cout << endl; - } - } - cout << endl; - cout << "factor groups:" << endl; - count = 0; - for (FactorSignMap::const_iterator it = factorGroups.begin(); - it != factorGroups.end(); it++) { - const FactorSet& groupMembers = it->second; - if (groupMembers.size() > 0) { - cout << ++count << ": " ; - //if (groupMembers.size() > 1) { - for (unsigned i = 0; i < groupMembers.size(); i++) { - cout << groupMembers[i]->getLabel() << " " ; - } - //} - cout << endl; - } - } -} - diff --git a/packages/CLPBN/clpbn/bp/LiftedFG.h b/packages/CLPBN/clpbn/bp/LiftedFG.h deleted file mode 100644 index 4a2518fc1..000000000 --- a/packages/CLPBN/clpbn/bp/LiftedFG.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef BP_LIFTED_FG_H -#define BP_LIFTED_FG_H - -#include - -#include "FactorGraph.h" -#include "FgVarNode.h" -#include "Factor.h" -#include "Shared.h" - -class VarCluster; -class FactorCluster; -class Distribution; - -typedef long Color; -typedef vector Signature; -typedef vector VarClusterSet; -typedef vector FactorClusterSet; - -typedef map VarSignMap; -typedef map FactorSignMap; - -typedef map > VarColorMap; -typedef map DistColorMap; - -typedef map Vid2VarCluster; - - -class VarCluster -{ - public: - VarCluster (CFgVarSet vs) - { - for (unsigned i = 0; i < vs.size(); i++) { - groundVars_.push_back (vs[i]); - } - } - - void addFactorCluster (FactorCluster* fc) - { - factorClusters_.push_back (fc); - } - - const FactorClusterSet& getFactorClusters (void) const - { - return factorClusters_; - } - - FgVarNode* getRepresentativeVariable (void) const { return representVar_; } - void setRepresentativeVariable (FgVarNode* v) { representVar_ = v; } - CFgVarSet getGroundFgVarNodes (void) const { return groundVars_; } - - private: - FgVarSet groundVars_; - FactorClusterSet factorClusters_; - FgVarNode* representVar_; -}; - - -class FactorCluster -{ - public: - FactorCluster (CFactorSet groundFactors, const VarClusterSet& vcs) - { - groundFactors_ = groundFactors; - varClusters_ = vcs; - for (unsigned i = 0; i < varClusters_.size(); i++) { - varClusters_[i]->addFactorCluster (this); - } - } - - const VarClusterSet& getVarClusters (void) const - { - return varClusters_; - } - - bool containsGround (const Factor* f) - { - for (unsigned i = 0; i < groundFactors_.size(); i++) { - if (groundFactors_[i] == f) { - return true; - } - } - return false; - } - - Factor* getRepresentativeFactor (void) const { return representFactor_; } - void setRepresentativeFactor (Factor* f) { representFactor_ = f; } - CFactorSet getGroundFactors (void) const { return groundFactors_; } - - - private: - FactorSet groundFactors_; - VarClusterSet varClusters_; - Factor* representFactor_; -}; - - -class LiftedFG -{ - public: - LiftedFG (const FactorGraph&); - ~LiftedFG (void); - - FactorGraph* getCompressedFactorGraph (void); - unsigned getGroundEdgeCount (FactorCluster*, VarCluster*) const; - void printGroups (const VarSignMap& varGroups, - const FactorSignMap& factorGroups) const; - - FgVarNode* getEquivalentVariable (Vid vid) - { - VarCluster* vc = vid2VarCluster_.find (vid)->second; - return vc->getRepresentativeVariable(); - } - - const VarClusterSet& getVariableClusters (void) { return varClusters_; } - const FactorClusterSet& getFactorClusters (void) { return factorClusters_; } - - private: - string getSignatureId (FgVarNode*) const; - string getSignatureId (Factor*) const; - - Color getFreeColor (void) { return ++freeColor_ -1; } - Color getColor (FgVarNode* v) const { return varColors_[v->getIndex()]; } - Color getColor (Factor* f) const { return factorColors_[f->getIndex()]; } - - void setColor (FgVarNode* v, Color c) - { - varColors_[v->getIndex()] = c; - } - - void setColor (Factor* f, Color c) - { - factorColors_[f->getIndex()] = c; - } - - VarCluster* getVariableCluster (Vid vid) const - { - return vid2VarCluster_.find (vid)->second; - } - - Color freeColor_; - vector varColors_; - vector factorColors_; - VarClusterSet varClusters_; - FactorClusterSet factorClusters_; - Vid2VarCluster vid2VarCluster_; - const FactorGraph* groundFg_; -}; - -#endif // BP_LIFTED_FG_H - diff --git a/packages/CLPBN/clpbn/bp/SPSolver.cpp b/packages/CLPBN/clpbn/bp/SPSolver.cpp deleted file mode 100644 index f2ec74fba..000000000 --- a/packages/CLPBN/clpbn/bp/SPSolver.cpp +++ /dev/null @@ -1,470 +0,0 @@ -#include -#include - -#include - -#include "SPSolver.h" -#include "FactorGraph.h" -#include "FgVarNode.h" -#include "Factor.h" -#include "Shared.h" - - -SPSolver::SPSolver (FactorGraph& fg) : Solver (&fg) -{ - fg_ = &fg; -} - - - -SPSolver::~SPSolver (void) -{ - for (unsigned i = 0; i < varsI_.size(); i++) { - delete varsI_[i]; - } - for (unsigned i = 0; i < factorsI_.size(); i++) { - delete factorsI_[i]; - } - for (unsigned i = 0; i < links_.size(); i++) { - delete links_[i]; - } -} - - - -void -SPSolver::runTreeSolver (void) -{ - CFactorSet factors = fg_->getFactors(); - bool finish = false; - while (!finish) { - finish = true; - for (unsigned i = 0; i < factors.size(); i++) { - CLinkSet links = factorsI_[factors[i]->getIndex()]->getLinks(); - for (unsigned j = 0; j < links.size(); j++) { - if (!links[j]->messageWasSended()) { - if (readyToSendMessage(links[j])) { - links[j]->setNextMessage (getFactor2VarMsg (links[j])); - links[j]->updateMessage(); - } - finish = false; - } - } - } - } -} - - - -bool -SPSolver::readyToSendMessage (const Link* link) const -{ - CFgVarSet factorVars = link->getFactor()->getFgVarNodes(); - for (unsigned i = 0; i < factorVars.size(); i++) { - if (factorVars[i] != link->getVariable()) { - CLinkSet links = varsI_[factorVars[i]->getIndex()]->getLinks(); - for (unsigned j = 0; j < links.size(); j++) { - if (links[j]->getFactor() != link->getFactor() && - !links[j]->messageWasSended()) { - return false; - } - } - } - } - return true; -} - - - -void -SPSolver::runSolver (void) -{ - initializeSolver(); - runTreeSolver(); - return; - nIter_ = 0; - while (!converged() && nIter_ < SolverOptions::maxIter) { - - nIter_ ++; - if (DL >= 2) { - cout << endl; - cout << "****************************************" ; - cout << "****************************************" ; - cout << endl; - cout << " Iteration " << nIter_ << endl; - cout << "****************************************" ; - cout << "****************************************" ; - cout << endl; - } - - switch (SolverOptions::schedule) { - case SolverOptions::S_SEQ_RANDOM: - random_shuffle (links_.begin(), links_.end()); - // no break - - case SolverOptions::S_SEQ_FIXED: - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->setNextMessage (getFactor2VarMsg (links_[i])); - links_[i]->updateMessage(); - } - break; - - case SolverOptions::S_PARALLEL: - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->setNextMessage (getFactor2VarMsg (links_[i])); - } - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->updateMessage(); - } - break; - - case SolverOptions::S_MAX_RESIDUAL: - maxResidualSchedule(); - break; - } - } - - if (DL >= 2) { - cout << endl; - if (nIter_ < SolverOptions::maxIter) { - cout << "Loopy Sum-Product converged in " ; - cout << nIter_ << " iterations" << endl; - } else { - cout << "The maximum number of iterations was hit, terminating..." ; - cout << endl; - } - } -} - - - -ParamSet -SPSolver::getPosterioriOf (Vid vid) const -{ - assert (fg_->getFgVarNode (vid)); - FgVarNode* var = fg_->getFgVarNode (vid); - ParamSet probs; - - if (var->hasEvidence()) { - probs.resize (var->getDomainSize(), 0.0); - probs[var->getEvidence()] = 1.0; - } else { - probs.resize (var->getDomainSize(), 1.0); - CLinkSet links = varsI_[var->getIndex()]->getLinks(); - for (unsigned i = 0; i < links.size(); i++) { - CParamSet msg = links[i]->getMessage(); - for (unsigned j = 0; j < msg.size(); j++) { - probs[j] *= msg[j]; - } - } - Util::normalize (probs); - } - return probs; -} - - - -ParamSet -SPSolver::getJointDistributionOf (const VidSet& jointVids) -{ - FgVarSet jointVars; - unsigned dsize = 1; - for (unsigned i = 0; i < jointVids.size(); i++) { - FgVarNode* varNode = fg_->getFgVarNode (jointVids[i]); - dsize *= varNode->getDomainSize(); - jointVars.push_back (varNode); - } - - unsigned maxVid = std::numeric_limits::max(); - FgVarNode* junctionVar = new FgVarNode (maxVid, dsize); - FgVarSet factorVars = { junctionVar }; - for (unsigned i = 0; i < jointVars.size(); i++) { - factorVars.push_back (jointVars[i]); - } - - unsigned nParams = dsize * dsize; - ParamSet params (nParams); - for (unsigned i = 0; i < nParams; i++) { - unsigned row = i / dsize; - unsigned col = i % dsize; - if (row == col) { - params[i] = 1; - } else { - params[i] = 0; - } - } - - Distribution* dist = new Distribution (params, maxVid); - Factor* newFactor = new Factor (factorVars, dist); - fg_->addVariable (junctionVar); - fg_->addFactor (newFactor); - - runSolver(); - ParamSet results = getPosterioriOf (maxVid); - deleteJunction (newFactor, junctionVar); - - return results; -} - - - -void -SPSolver::initializeSolver (void) -{ - fg_->setIndexes(); - - CFgVarSet vars = fg_->getFgVarNodes(); - for (unsigned i = 0; i < varsI_.size(); i++) { - delete varsI_[i]; - } - varsI_.reserve (vars.size()); - for (unsigned i = 0; i < vars.size(); i++) { - varsI_.push_back (new SPNodeInfo()); - } - - CFactorSet factors = fg_->getFactors(); - for (unsigned i = 0; i < factorsI_.size(); i++) { - delete factorsI_[i]; - } - factorsI_.reserve (factors.size()); - for (unsigned i = 0; i < factors.size(); i++) { - factorsI_.push_back (new SPNodeInfo()); - } - - for (unsigned i = 0; i < links_.size(); i++) { - delete links_[i]; - } - createLinks(); - - for (unsigned i = 0; i < links_.size(); i++) { - Factor* source = links_[i]->getFactor(); - FgVarNode* dest = links_[i]->getVariable(); - varsI_[dest->getIndex()]->addLink (links_[i]); - factorsI_[source->getIndex()]->addLink (links_[i]); - } -} - - - -void -SPSolver::createLinks (void) -{ - CFactorSet factors = fg_->getFactors(); - for (unsigned i = 0; i < factors.size(); i++) { - CFgVarSet neighbors = factors[i]->getFgVarNodes(); - for (unsigned j = 0; j < neighbors.size(); j++) { - links_.push_back (new Link (factors[i], neighbors[j])); - } - } -} - - - -void -SPSolver::deleteJunction (Factor* f, FgVarNode* v) -{ - fg_->removeFactor (f); - f->freeDistribution(); - delete f; - fg_->removeVariable (v); - delete v; -} - - - -bool -SPSolver::converged (void) -{ - // this can happen if the graph is fully disconnected - if (links_.size() == 0) { - return true; - } - if (nIter_ == 0 || nIter_ == 1) { - return false; - } - bool converged = true; - if (SolverOptions::schedule == SolverOptions::S_MAX_RESIDUAL) { - Param maxResidual = (*(sortedOrder_.begin()))->getResidual(); - if (maxResidual < SolverOptions::accuracy) { - converged = true; - } else { - converged = false; - } - } else { - for (unsigned i = 0; i < links_.size(); i++) { - double residual = links_[i]->getResidual(); - if (DL >= 2) { - cout << links_[i]->toString() + " residual = " << residual << endl; - } - if (residual > SolverOptions::accuracy) { - converged = false; - if (DL == 0) break; - } - } - } - return converged; -} - - - -void -SPSolver::maxResidualSchedule (void) -{ - if (nIter_ == 1) { - for (unsigned i = 0; i < links_.size(); i++) { - links_[i]->setNextMessage (getFactor2VarMsg (links_[i])); - SortedOrder::iterator it = sortedOrder_.insert (links_[i]); - linkMap_.insert (make_pair (links_[i], it)); - if (DL >= 2 && DL < 5) { - cout << "calculating " << links_[i]->toString() << endl; - } - } - return; - } - - for (unsigned c = 0; c < links_.size(); c++) { - if (DL >= 2) { - cout << endl << "current residuals:" << endl; - for (SortedOrder::iterator it = sortedOrder_.begin(); - it != sortedOrder_.end(); it ++) { - cout << " " << setw (30) << left << (*it)->toString(); - cout << "residual = " << (*it)->getResidual() << endl; - } - } - - SortedOrder::iterator it = sortedOrder_.begin(); - Link* link = *it; - if (DL >= 2) { - cout << "updating " << (*sortedOrder_.begin())->toString() << endl; - } - if (link->getResidual() < SolverOptions::accuracy) { - return; - } - link->updateMessage(); - link->clearResidual(); - sortedOrder_.erase (it); - linkMap_.find (link)->second = sortedOrder_.insert (link); - - // update the messages that depend on message source --> destin - CFactorSet factorNeighbors = link->getVariable()->getFactors(); - for (unsigned i = 0; i < factorNeighbors.size(); i++) { - if (factorNeighbors[i] != link->getFactor()) { - CLinkSet links = factorsI_[factorNeighbors[i]->getIndex()]->getLinks(); - for (unsigned j = 0; j < links.size(); j++) { - if (links[j]->getVariable() != link->getVariable()) { - if (DL >= 2 && DL < 5) { - cout << " calculating " << links[j]->toString() << endl; - } - links[j]->setNextMessage (getFactor2VarMsg (links[j])); - LinkMap::iterator iter = linkMap_.find (links[j]); - sortedOrder_.erase (iter->second); - iter->second = sortedOrder_.insert (links[j]); - } - } - } - } - } -} - - - -ParamSet -SPSolver::getFactor2VarMsg (const Link* link) const -{ - const Factor* src = link->getFactor(); - const FgVarNode* dest = link->getVariable(); - CFgVarSet neighbors = src->getFgVarNodes(); - CLinkSet links = factorsI_[src->getIndex()]->getLinks(); - // calculate the product of messages that were sent - // to factor `src', except from var `dest' - Factor result (*src); - Factor temp; - if (DL >= 5) { - cout << "calculating " ; - cout << src->getLabel() << " --> " << dest->getLabel(); - cout << endl; - } - for (unsigned i = 0; i < neighbors.size(); i++) { - if (links[i]->getVariable() != dest) { - if (DL >= 5) { - cout << " message from " << links[i]->getVariable()->getLabel(); - cout << ": " ; - ParamSet p = getVar2FactorMsg (links[i]); - cout << endl; - Factor temp2 (links[i]->getVariable(), p); - temp.multiplyByFactor (temp2); - temp2.freeDistribution(); - } else { - Factor temp2 (links[i]->getVariable(), getVar2FactorMsg (links[i])); - temp.multiplyByFactor (temp2); - temp2.freeDistribution(); - } - } - } - if (links.size() >= 2) { - result.multiplyByFactor (temp, &(src->getCptEntries())); - if (DL >= 5) { - cout << " message product: " ; - cout << Util::parametersToString (temp.getParameters()) << endl; - cout << " factor product: " ; - cout << Util::parametersToString (src->getParameters()); - cout << " x " ; - cout << Util::parametersToString (temp.getParameters()); - cout << " = " ; - cout << Util::parametersToString (result.getParameters()) << endl; - } - temp.freeDistribution(); - } - - for (unsigned i = 0; i < links.size(); i++) { - if (links[i]->getVariable() != dest) { - result.removeVariable (links[i]->getVariable()); - } - } - if (DL >= 5) { - cout << " final message: " ; - cout << Util::parametersToString (result.getParameters()) << endl << endl; - } - ParamSet msg = result.getParameters(); - result.freeDistribution(); - return msg; -} - - - -ParamSet -SPSolver::getVar2FactorMsg (const Link* link) const -{ - const FgVarNode* src = link->getVariable(); - const Factor* dest = link->getFactor(); - ParamSet msg; - if (src->hasEvidence()) { - msg.resize (src->getDomainSize(), 0.0); - msg[src->getEvidence()] = 1.0; - if (DL >= 5) { - cout << Util::parametersToString (msg); - } - } else { - msg.resize (src->getDomainSize(), 1.0); - } - if (DL >= 5) { - cout << Util::parametersToString (msg); - } - CLinkSet links = varsI_[src->getIndex()]->getLinks(); - for (unsigned i = 0; i < links.size(); i++) { - if (links[i]->getFactor() != dest) { - CParamSet msgFromFactor = links[i]->getMessage(); - for (unsigned j = 0; j < msgFromFactor.size(); j++) { - msg[j] *= msgFromFactor[j]; - } - if (DL >= 5) { - cout << " x " << Util::parametersToString (msgFromFactor); - } - } - } - if (DL >= 5) { - cout << " = " << Util::parametersToString (msg); - } - return msg; -} - diff --git a/packages/CLPBN/clpbn/bp/SPSolver.h b/packages/CLPBN/clpbn/bp/SPSolver.h deleted file mode 100644 index bc4d64ade..000000000 --- a/packages/CLPBN/clpbn/bp/SPSolver.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef BP_SP_SOLVER_H -#define BP_SP_SOLVER_H - -#include -#include - -#include "Solver.h" -#include "FgVarNode.h" -#include "Factor.h" - -using namespace std; - -class FactorGraph; -class SPSolver; - - -class Link -{ - public: - Link (Factor* f, FgVarNode* v) - { - factor_ = f; - var_ = v; - currMsg_.resize (v->getDomainSize(), 1); - nextMsg_.resize (v->getDomainSize(), 1); - msgSended_ = false; - residual_ = 0.0; - } - - void setMessage (ParamSet msg) - { - Util::normalize (msg); - residual_ = Util::getMaxNorm (currMsg_, msg); - currMsg_ = msg; - } - - void setNextMessage (CParamSet msg) - { - nextMsg_ = msg; - Util::normalize (nextMsg_); - residual_ = Util::getMaxNorm (currMsg_, nextMsg_); - } - - void updateMessage (void) - { - currMsg_ = nextMsg_; - msgSended_ = true; - } - - string toString (void) const - { - stringstream ss; - ss << factor_->getLabel(); - ss << " -- " ; - ss << var_->getLabel(); - return ss.str(); - } - - Factor* getFactor (void) const { return factor_; } - FgVarNode* getVariable (void) const { return var_; } - CParamSet getMessage (void) const { return currMsg_; } - bool messageWasSended (void) const { return msgSended_; } - double getResidual (void) const { return residual_; } - void clearResidual (void) { residual_ = 0.0; } - - private: - Factor* factor_; - FgVarNode* var_; - ParamSet currMsg_; - ParamSet nextMsg_; - bool msgSended_; - double residual_; -}; - - -class SPNodeInfo -{ - public: - void addLink (Link* link) { links_.push_back (link); } - CLinkSet getLinks (void) { return links_; } - - private: - LinkSet links_; -}; - - -class SPSolver : public Solver -{ - public: - SPSolver (FactorGraph&); - virtual ~SPSolver (void); - - void runSolver (void); - virtual ParamSet getPosterioriOf (Vid) const; - ParamSet getJointDistributionOf (CVidSet); - - protected: - virtual void initializeSolver (void); - void runTreeSolver (void); - bool readyToSendMessage (const Link*) const; - virtual void createLinks (void); - virtual void deleteJunction (Factor*, FgVarNode*); - bool converged (void); - virtual void maxResidualSchedule (void); - virtual ParamSet getFactor2VarMsg (const Link*) const; - virtual ParamSet getVar2FactorMsg (const Link*) const; - - struct CompareResidual { - inline bool operator() (const Link* link1, const Link* link2) - { - return link1->getResidual() > link2->getResidual(); - } - }; - - FactorGraph* fg_; - LinkSet links_; - vector varsI_; - vector factorsI_; - unsigned nIter_; - - typedef multiset SortedOrder; - SortedOrder sortedOrder_; - - typedef map LinkMap; - LinkMap linkMap_; - -}; - -#endif // BP_SP_SOLVER_H - diff --git a/packages/CLPBN/clpbn/bp/Variable.h b/packages/CLPBN/clpbn/bp/Variable.h deleted file mode 100644 index e3e0a95db..000000000 --- a/packages/CLPBN/clpbn/bp/Variable.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef BP_VARIABLE_H -#define BP_VARIABLE_H - -#include - -#include - -#include "Shared.h" - -using namespace std; - -class Variable -{ - public: - - Variable (const Variable* v) - { - vid_ = v->getVarId(); - dsize_ = v->getDomainSize(); - if (v->hasDomain()) { - domain_ = v->getDomain(); - dsize_ = domain_.size(); - } else { - dsize_ = v->getDomainSize(); - } - evidence_ = v->getEvidence(); - if (v->hasLabel()) { - label_ = new string (v->getLabel()); - } else { - label_ = 0; - } - } - - Variable (Vid vid) - { - this->vid_ = vid; - this->dsize_ = 0; - this->evidence_ = NO_EVIDENCE; - this->label_ = 0; - } - - Variable (Vid vid, unsigned dsize, int evidence = NO_EVIDENCE, - const string& lbl = string()) - { - assert (dsize != 0); - assert (evidence < (int)dsize); - this->vid_ = vid; - this->dsize_ = dsize; - this->evidence_ = evidence; - if (!lbl.empty()) { - this->label_ = new string (lbl); - } else { - this->label_ = 0; - } - } - - Variable (Vid vid, const Domain& domain, int evidence = NO_EVIDENCE, - const string& lbl = string()) - { - assert (!domain.empty()); - assert (evidence < (int)domain.size()); - this->vid_ = vid; - this->dsize_ = domain.size(); - this->domain_ = domain; - this->evidence_ = evidence; - if (!lbl.empty()) { - this->label_ = new string (lbl); - } else { - this->label_ = 0; - } - } - - ~Variable (void) - { - delete label_; - } - - unsigned getVarId (void) const { return vid_; } - unsigned getIndex (void) const { return index_; } - void setIndex (unsigned idx) { index_ = idx; } - unsigned getDomainSize (void) const { return dsize_; } - bool hasEvidence (void) const { return evidence_ != NO_EVIDENCE; } - int getEvidence (void) const { return evidence_; } - bool hasDomain (void) const { return !domain_.empty(); } - bool hasLabel (void) const { return label_ != 0; } - - bool isValidStateIndex (int index) - { - return index >= 0 && index < (int)dsize_; - } - - bool isValidState (const string& state) - { - return find (domain_.begin(), domain_.end(), state) != domain_.end(); - } - - Domain getDomain (void) const - { - assert (dsize_ != 0); - if (domain_.size() == 0) { - Domain d; - for (unsigned i = 0; i < dsize_; i++) { - stringstream ss; - ss << "x" << i ; - d.push_back (ss.str()); - } - return d; - } else { - return domain_; - } - } - - void setDomainSize (unsigned dsize) - { - assert (dsize != 0); - dsize_ = dsize; - } - - void setDomain (const Domain& domain) - { - assert (!domain.empty()); - domain_ = domain; - dsize_ = domain.size(); - } - - void setEvidence (int ev) - { - assert (ev < dsize_); - evidence_ = ev; - } - - void setEvidence (const string& ev) - { - assert (isValidState (ev)); - for (unsigned i = 0; i < domain_.size(); i++) { - if (domain_[i] == ev) { - evidence_ = i; - } - } - } - - void setLabel (const string& label) - { - label_ = new string (label); - } - - string getLabel (void) const - { - if (label_ == 0) { - stringstream ss; - ss << "v" << vid_; - return ss.str(); - } else { - return *label_; - } - } - - - private: - DISALLOW_COPY_AND_ASSIGN (Variable); - - Vid vid_; - unsigned dsize_; - int evidence_; - Domain domain_; - string* label_; - unsigned index_; - -}; - -#endif // BP_VARIABLE_H - diff --git a/packages/CLPBN/clpbn/bp/callgrind.h b/packages/CLPBN/clpbn/bp/callgrind.h deleted file mode 100644 index d36b6f4eb..000000000 --- a/packages/CLPBN/clpbn/bp/callgrind.h +++ /dev/null @@ -1,147 +0,0 @@ - -/* - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (callgrind.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of callgrind, a valgrind tool for cache simulation - and call tree tracing. - - Copyright (C) 2003-2010 Josef Weidendorfer. All rights reserved. - - 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. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. 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. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (callgrind.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - -#ifndef __CALLGRIND_H -#define __CALLGRIND_H - -#include "valgrind.h" - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. - - The identification ('C','T') for Callgrind has historical - reasons: it was called "Calltree" before. Besides, ('C','G') would - clash with cachegrind. - */ - -typedef - enum { - VG_USERREQ__DUMP_STATS = VG_USERREQ_TOOL_BASE('C','T'), - VG_USERREQ__ZERO_STATS, - VG_USERREQ__TOGGLE_COLLECT, - VG_USERREQ__DUMP_STATS_AT, - VG_USERREQ__START_INSTRUMENTATION, - VG_USERREQ__STOP_INSTRUMENTATION - } Vg_CallgrindClientRequest; - -/* Dump current state of cost centers, and zero them afterwards */ -#define CALLGRIND_DUMP_STATS \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DUMP_STATS, \ - 0, 0, 0, 0, 0); \ - } - -/* Dump current state of cost centers, and zero them afterwards. - The argument is appended to a string stating the reason which triggered - the dump. This string is written as a description field into the - profile data dump. */ -#define CALLGRIND_DUMP_STATS_AT(pos_str) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DUMP_STATS_AT, \ - pos_str, 0, 0, 0, 0); \ - } - -/* Zero cost centers */ -#define CALLGRIND_ZERO_STATS \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__ZERO_STATS, \ - 0, 0, 0, 0, 0); \ - } - -/* Toggles collection state. - The collection state specifies whether the happening of events - should be noted or if they are to be ignored. Events are noted - by increment of counters in a cost center */ -#define CALLGRIND_TOGGLE_COLLECT \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__TOGGLE_COLLECT, \ - 0, 0, 0, 0, 0); \ - } - -/* Start full callgrind instrumentation if not already switched on. - When cache simulation is done, it will flush the simulated cache; - this will lead to an artifical cache warmup phase afterwards with - cache misses which would not have happened in reality. */ -#define CALLGRIND_START_INSTRUMENTATION \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__START_INSTRUMENTATION, \ - 0, 0, 0, 0, 0); \ - } - -/* Stop full callgrind instrumentation if not already switched off. - This flushes Valgrinds translation cache, and does no additional - instrumentation afterwards, which effectivly will run at the same - speed as the "none" tool (ie. at minimal slowdown). - Use this to bypass Callgrind aggregation for uninteresting code parts. - To start Callgrind in this mode to ignore the setup phase, use - the option "--instr-atstart=no". */ -#define CALLGRIND_STOP_INSTRUMENTATION \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STOP_INSTRUMENTATION, \ - 0, 0, 0, 0, 0); \ - } - -#endif /* __CALLGRIND_H */ diff --git a/packages/CLPBN/clpbn/bp/examples/cbp_example.uai b/packages/CLPBN/clpbn/bp/examples/cbp_example.uai new file mode 100644 index 000000000..239ec4ab1 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/cbp_example.uai @@ -0,0 +1,14 @@ +MARKOV +3 +2 2 2 +2 +2 0 1 +2 2 1 + + +4 + 1.2 1.4 2.0 0.4 + +4 + 1.2 1.4 2.0 0.4 + diff --git a/packages/CLPBN/clpbn/bp/examples/loop.yap b/packages/CLPBN/clpbn/bp/examples/loop.yap deleted file mode 100644 index c18784975..000000000 --- a/packages/CLPBN/clpbn/bp/examples/loop.yap +++ /dev/null @@ -1,53 +0,0 @@ - -:- use_module(library(clpbn)). - -:- set_clpbn_flag(solver, bp). - -% -% A E -% / \ / -% / \ / -% B C -% \ / -% \ / -% D -% - -a(A) :- - a_table(ADist), - { A = a with p([a1, a2], ADist) }. - -b(B) :- - a(A), - b_table(BDist), - { B = b with p([b1, b2], BDist, [A]) }. - -c(C) :- - a(A), - c_table(CDist), - { C = c with p([c1, c2], CDist, [A]) }. - -d(D) :- - b(B), - c(C), - d_table(DDist), - { D = d with p([d1, d2], DDist, [B, C]) }. - -e(E) :- - e_table(EDist), - { E = e with p([e1, e2], EDist) }. - - -a_table([0.005, 0.995]). - -b_table([0.02, 0.97, - 0.88, 0.03]). - -c_table([0.55, 0.94, - 0.45, 0.06]). - -d_table([0.192, 0.98, 0.33, 0.013, - 0.908, 0.02, 0.77, 0.987]). - -e_table([0.055, 0.945]). - diff --git a/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_compress.sh b/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_compress.sh new file mode 100644 index 000000000..0261b7a35 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_compress.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +cp ~/bin/yap ~/bin/town_comp +YAP=~/bin/town_comp + +#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log +OUT_FILE_NAME=bp_compress.log +rm -f $OUT_FILE_NAME +rm -f ignore.$OUT_FILE_NAME + + +function run_solver +{ +if [ $2 = bp ] +then + extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\) + extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\) + extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\) +else + extra_flag1=true + extra_flag2=true + extra_flag3=true +fi +/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME +[$1]. +clpbn:set_clpbn_flag(solver,$2), + clpbn_bp:use_log_space, + $extra_flag1, $extra_flag2, $extra_flag3, + run_query(_R), + open("$OUT_FILE_NAME", 'append',S), + format(S, '$3: ~15+ ',[]), + close(S). +EOF +} + + +function run_all_graphs +{ + echo "*******************************************************************" >> "$OUT_FILE_NAME" + echo "results for solver $2" >> $OUT_FILE_NAME + echo "*******************************************************************" >> "$OUT_FILE_NAME" + run_solver town_1000 $1 town_1000 $3 $4 $5 + run_solver town_5000 $1 town_5000 $3 $4 $5 + run_solver town_10000 $1 town_10000 $3 $4 $5 + run_solver town_50000 $1 town_50000 $3 $4 $5 + run_solver town_100000 $1 town_100000 $3 $4 $5 + run_solver town_500000 $1 town_500000 $3 $4 $5 + run_solver town_1000000 $1 town_1000000 $3 $4 $5 + run_solver town_2500000 $1 town_2500000 $3 $4 $5 + run_solver town_5000000 $1 town_5000000 $3 $4 $5 + run_solver town_7500000 $1 town_7500000 $3 $4 $5 + run_solver town_10000000 $1 town_10000000 $3 $4 $5 +} + +run_solver town_10000 "bp(compress,seq_fixed)" town_10000 compress seq_fixed true +exit + +########## +run_all_graphs bp "bp(compress,seq_fixed) " compress seq_fixed true + diff --git a/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_convert.sh b/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_convert.sh new file mode 100644 index 000000000..133cf71fb --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_convert.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +YAP=~/bin/town_conv + +#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log +OUT_FILE_NAME=bp_convert.log +rm -f $OUT_FILE_NAME +rm -f ignore.$OUT_FILE_NAME + + +function run_solver +{ +if [ $2 = bp ] +then + extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\) + extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\) + extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\) +else + extra_flag1=true + extra_flag2=true + extra_flag3=true +fi +/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME +[$1]. +clpbn:set_clpbn_flag(solver,$2), + clpbn_bp:use_log_space, + $extra_flag1, $extra_flag2, $extra_flag3, + run_query(_R), + open("$OUT_FILE_NAME", 'append',S), + format(S, '$3: ~15+ ',[]), + close(S). +EOF +} + + +function run_all_graphs +{ + echo "*******************************************************************" >> "$OUT_FILE_NAME" + echo "results for solver $2" >> $OUT_FILE_NAME + echo "*******************************************************************" >> "$OUT_FILE_NAME" + run_solver town_1000 $1 town_1000 $3 $4 $5 + run_solver town_5000 $1 town_5000 $3 $4 $5 + run_solver town_10000 $1 town_10000 $3 $4 $5 + run_solver town_50000 $1 town_50000 $3 $4 $5 + run_solver town_100000 $1 town_100000 $3 $4 $5 + run_solver town_500000 $1 town_500000 $3 $4 $5 + run_solver town_1000000 $1 town_1000000 $3 $4 $5 +} + +run_all_graphs bp "bp(convert,seq_fixed) " convert seq_fixed false + diff --git a/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_normal.sh b/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_normal.sh new file mode 100644 index 000000000..6284282cb --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/run_town_bp_normal.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +YAP=~/bin/town_norm + +#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log +OUT_FILE_NAME=bp_normal.log +rm -f $OUT_FILE_NAME +rm -f ignore.$OUT_FILE_NAME + + +function run_solver +{ +if [ $2 = bp ] +then + extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\) + extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\) + extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\) +else + extra_flag1=true + extra_flag2=true + extra_flag3=true +fi +/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME +[$1]. +clpbn:set_clpbn_flag(solver,$2), + clpbn_bp:use_log_space, + $extra_flag1, $extra_flag2, $extra_flag3, + run_query(_R), + open("$OUT_FILE_NAME", 'append',S), + format(S, '$3: ~15+ ',[]), + close(S). +EOF +} + + +function run_all_graphs +{ + echo "*******************************************************************" >> "$OUT_FILE_NAME" + echo "results for solver $2" >> $OUT_FILE_NAME + echo "*******************************************************************" >> "$OUT_FILE_NAME" + run_solver town_1000 $1 town_1000 $3 $4 $5 + run_solver town_5000 $1 town_5000 $3 $4 $5 + run_solver town_10000 $1 town_10000 $3 $4 $5 + run_solver town_50000 $1 town_50000 $3 $4 $5 + run_solver town_100000 $1 town_100000 $3 $4 $5 + run_solver town_500000 $1 town_500000 $3 $4 $5 + run_solver town_1000000 $1 town_1000000 $3 $4 $5 +} + +run_all_graphs bp "bp(normal,seq_fixed) " normal seq_fixed false diff --git a/packages/CLPBN/clpbn/bp/examples/town/run_town_gibbs_tests.sh b/packages/CLPBN/clpbn/bp/examples/town/run_town_gibbs_tests.sh new file mode 100644 index 000000000..ac1f10781 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/run_town_gibbs_tests.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +YAP=~/bin/town_gibbs + +#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log +OUT_FILE_NAME=gibbs.log +rm -f $OUT_FILE_NAME +rm -f ignore.$OUT_FILE_NAME + + +function run_solver +{ +if [ $2 = bp ] +then + extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\) + extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\) + extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\) +else + extra_flag1=true + extra_flag2=true + extra_flag3=true +fi +/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME +[$1]. +clpbn:set_clpbn_flag(solver,$2), + clpbn_bp:use_log_space, + $extra_flag1, $extra_flag2, $extra_flag3, + run_query(_R), + open("$OUT_FILE_NAME", 'append',S), + format(S, '$3: ~15+ ',[]), + close(S). +EOF +} + + +function run_all_graphs +{ + echo "*******************************************************************" >> "$OUT_FILE_NAME" + echo "results for solver $2" >> $OUT_FILE_NAME + echo "*******************************************************************" >> "$OUT_FILE_NAME" + run_solver town_1000 $1 town_1000 $3 $4 $5 + run_solver town_5000 $1 town_5000 $3 $4 $5 + run_solver town_10000 $1 town_10000 $3 $4 $5 + run_solver town_50000 $1 town_50000 $3 $4 $5 + run_solver town_100000 $1 town_100000 $3 $4 $5 + run_solver town_500000 $1 town_500000 $3 $4 $5 + run_solver town_1000000 $1 town_1000000 $3 $4 $5 +} + +run_all_graphs gibbs "gibbs " + diff --git a/packages/CLPBN/clpbn/bp/examples/town/run_town_jt_tests.sh b/packages/CLPBN/clpbn/bp/examples/town/run_town_jt_tests.sh new file mode 100644 index 000000000..a75483517 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/run_town_jt_tests.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +YAP=~/bin/town_jt + +#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log +OUT_FILE_NAME=jt.log +rm -f $OUT_FILE_NAME +rm -f ignore.$OUT_FILE_NAME + + +function run_solver +{ +if [ $2 = bp ] +then + extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\) + extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\) + extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\) +else + extra_flag1=true + extra_flag2=true + extra_flag3=true +fi +/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME +[$1]. +clpbn:set_clpbn_flag(solver,$2), + clpbn_bp:use_log_space, + $extra_flag1, $extra_flag2, $extra_flag3, + run_query(_R), + open("$OUT_FILE_NAME", 'append',S), + format(S, '$3: ~15+ ',[]), + close(S). +EOF +} + + +function run_all_graphs +{ + echo "*******************************************************************" >> "$OUT_FILE_NAME" + echo "results for solver $2" >> $OUT_FILE_NAME + echo "*******************************************************************" >> "$OUT_FILE_NAME" + run_solver town_1000 $1 town_1000 $3 $4 $5 + run_solver town_5000 $1 town_5000 $3 $4 $5 + run_solver town_10000 $1 town_10000 $3 $4 $5 + run_solver town_50000 $1 town_50000 $3 $4 $5 + run_solver town_100000 $1 town_100000 $3 $4 $5 + run_solver town_500000 $1 town_500000 $3 $4 $5 + run_solver town_1000000 $1 town_1000000 $3 $4 $5 +} + +run_all_graphs jt "jt " + diff --git a/packages/CLPBN/clpbn/bp/examples/town/run_town_ve_tests.sh b/packages/CLPBN/clpbn/bp/examples/town/run_town_ve_tests.sh new file mode 100644 index 000000000..db5762a82 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/run_town_ve_tests.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +YAP=~/bin/town_ve + +#OUT_FILE_NAME=results`date "+ %H:%M:%S %d-%m-%Y"`.log +OUT_FILE_NAME=ve.log +rm -f $OUT_FILE_NAME +rm -f ignore.$OUT_FILE_NAME + + +function run_solver +{ +if [ $2 = bp ] +then + extra_flag1=clpbn_bp:set_solver_parameter\(run_mode,$4\) + extra_flag2=clpbn_bp:set_solver_parameter\(schedule,$5\) + extra_flag3=clpbn_bp:set_solver_parameter\(always_loopy_solver,$6\) +else + extra_flag1=true + extra_flag2=true + extra_flag3=true +fi +/usr/bin/time -o $OUT_FILE_NAME -a -f "real:%E\tuser:%U\tsys:%S" $YAP << EOF >> $OUT_FILE_NAME 2>> ignore.$OUT_FILE_NAME +[$1]. +clpbn:set_clpbn_flag(solver,$2), + clpbn_bp:use_log_space, + $extra_flag1, $extra_flag2, $extra_flag3, + run_query(_R), + open("$OUT_FILE_NAME", 'append',S), + format(S, '$3: ~15+ ',[]), + close(S). +EOF +} + + +function run_all_graphs +{ + echo "*******************************************************************" >> "$OUT_FILE_NAME" + echo "results for solver $2" >> $OUT_FILE_NAME + echo "*******************************************************************" >> "$OUT_FILE_NAME" + run_solver town_1000 $1 town_1000 $3 $4 $5 + run_solver town_5000 $1 town_5000 $3 $4 $5 + run_solver town_10000 $1 town_10000 $3 $4 $5 + run_solver town_50000 $1 town_50000 $3 $4 $5 + run_solver town_100000 $1 town_100000 $3 $4 $5 + run_solver town_500000 $1 town_500000 $3 $4 $5 + run_solver town_1000000 $1 town_1000000 $3 $4 $5 +} + +run_all_graphs ve "ve " + diff --git a/packages/CLPBN/clpbn/bp/examples/town/schema.yap b/packages/CLPBN/clpbn/bp/examples/town/schema.yap new file mode 100644 index 000000000..f33db80f7 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/schema.yap @@ -0,0 +1,65 @@ + +conservative_city(City, Cons) :- + cons_table(City, ConsDist), + { Cons = conservative_city(City) with p([y,n], ConsDist) }. + + +gender(X, Gender) :- + gender_table(X, GenderDist), + { Gender = gender(X) with p([m,f], GenderDist) }. + + +hair_color(X, Color) :- + lives(X, City), + conservative_city(City, Cons), + hair_color_table(X,ColorTable), + { Color = hair_color(X) with + p([t,f], ColorTable,[Cons]) }. + + +car_color(X, Color) :- + hair_color(X, HColor), + car_color_table(X,CColorTable), + { Color = car_color(X) with + p([t,f], CColorTable,[HColor]) }. + + +height(X, Height) :- + gender(X, Gender), + height_table(X,HeightTable), + { Height = height(X) with + p([t,f], HeightTable,[Gender]) }. + + +shoe_size(X, Shoesize) :- + height(X, Height), + shoe_size_table(X,ShoesizeTable), + { Shoesize = shoe_size(X) with + p([t,f], ShoesizeTable,[Height]) }. + + +guilty(X, Guilt) :- + guilty_table(X, GuiltDist), + { Guilt = guilty(X) with p([y,n], GuiltDist) }. + + +descn(X, Descn) :- + car_color(X, Car), + hair_color(X, Hair), + height(X, Height), + guilty(X, Guilt), + descn_table(X, DescTable), + { Descn = descn(X) with + p([t,f], DescTable,[Car,Hair,Height,Guilt]) }. + + +witness(City, Witness) :- + descn(joe, DescnJ), + descn(p2, Descn2), + wit_table(WitTable), + { Witness = witness(City) with + p([t,f], WitTable,[DescnJ, Descn2]) }. + + +:- ensure_loaded(tables). + diff --git a/packages/CLPBN/clpbn/bp/examples/town/tables.yap b/packages/CLPBN/clpbn/bp/examples/town/tables.yap new file mode 100644 index 000000000..e4503cbef --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/tables.yap @@ -0,0 +1,46 @@ + +cons_table(amsterdam, [0.2, 0.8]) :- !. +cons_table(_, [0.8, 0.2]). + + +gender_table(_, [0.55, 0.44]). + + +hair_color_table(_, + /* conservative_city */ + /* y n */ + [ 0.05, 0.1, + 0.95, 0.9 ]). + + +car_color_table(_, + /* t f */ + [ 0.9, 0.2, + 0.1, 0.8 ]). + + +height_table(_, + /* m f */ + [ 0.6, 0.4, + 0.4, 0.6 ]). + + +shoe_size_table(_, + /* t f */ + [ 0.9, 0.1, + 0.1, 0.9 ]). + + +guilty_table(_, [0.23, 0.77]). + + +descn_table(_, + /* color, hair, height, guilt */ + /* ttttt tttf ttft ttff tfttt tftf tfft tfff ttttt fttf ftft ftff ffttt fftf ffft ffff */ + [ 0.99, 0.5, 0.23, 0.88, 0.41, 0.3, 0.76, 0.87, 0.44, 0.43, 0.29, 0.72, 0.33, 0.91, 0.95, 0.92, + 0.01, 0.5, 0.77, 0.12, 0.59, 0.7, 0.24, 0.13, 0.56, 0.57, 0.61, 0.28, 0.77, 0.09, 0.05, 0.08]). + + +wit_table([0.2, 0.45, 0.24, 0.34, + 0.8, 0.55, 0.76, 0.66]). + diff --git a/packages/CLPBN/clpbn/bp/examples/town/town_generator.sh b/packages/CLPBN/clpbn/bp/examples/town/town_generator.sh new file mode 100644 index 000000000..2feb9a397 --- /dev/null +++ b/packages/CLPBN/clpbn/bp/examples/town/town_generator.sh @@ -0,0 +1,59 @@ +#!/home/tgomes/bin/yap -L -- + +/* +Steps: +1. generate N facts lives(I, nyc), 0 <= I < N. +2. generate evidence on descn for N people, *** except for 1 *** +3. Run query ?- guilty(joe, Guilty), witness(joe, t), descn(2,t), descn(3, f), descn(4, f) ... +*/ + +:- initialization(main). + + +main :- + unix(argv([H])), + generate_town(H). + + +generate_town(N) :- + atomic_concat(['town_', N, '.yap'], FileName), + open(FileName, 'write', S), + write(S, ':- source.\n'), + write(S, ':- style_check(all).\n'), + write(S, ':- yap_flag(unknown,error).\n'), + write(S, ':- yap_flag(write_strings,on).\n'), + write(S, ':- use_module(library(clpbn)).\n'), + write(S, ':- set_clpbn_flag(solver, bp).\n'), + write(S, ':- [-schema].\n\n'), + write(S, 'lives(_joe, nyc).\n'), + atom_number(N, N2), + generate_people(S, N2, 2), + write(S, '\nrun_query(Guilty) :- \n'), + write(S, '\tguilty(joe, Guilty),\n'), + write(S, '\twitness(nyc, t),\n'), + write(S, '\trunall(X, ev(X)).\n\n\n'), + write(S, 'runall(G, Wrapper) :-\n'), + write(S, '\tfindall(G, Wrapper, L),\n'), + write(S, '\texecute_all(L).\n\n\n'), + write(S, 'execute_all([]).\n'), + write(S, 'execute_all(G.L) :-\n'), + write(S, '\tcall(G),\n'), + write(S, '\texecute_all(L).\n\n\n'), + generate_query(S, N2, 2), + close(S). + + +generate_people(_, N, Counting1) :- !. +generate_people(S, N, Counting) :- + format(S, 'lives(p~w, nyc).~n', [Counting]), + Counting1 is Counting + 1, + generate_people(S, N, Counting1). + + +generate_query(S, N, Counting) :- + Counting > N, !. +generate_query(S, N, Counting) :- !, + format(S, 'ev(descn(p~w, t)).~n', [Counting]), + Counting1 is Counting + 1, + generate_query(S, N, Counting1). + diff --git a/packages/CLPBN/clpbn/bp/valgrind.h b/packages/CLPBN/clpbn/bp/valgrind.h deleted file mode 100644 index 0f5b37662..000000000 --- a/packages/CLPBN/clpbn/bp/valgrind.h +++ /dev/null @@ -1,4536 +0,0 @@ -/* -*- c -*- - ---------------------------------------------------------------- - - Notice that the following BSD-style license applies to this one - file (valgrind.h) only. The rest of Valgrind is licensed under the - terms of the GNU General Public License, version 2, unless - otherwise indicated. See the COPYING file in the source - distribution for details. - - ---------------------------------------------------------------- - - This file is part of Valgrind, a dynamic binary instrumentation - framework. - - Copyright (C) 2000-2010 Julian Seward. All rights reserved. - - 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. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. 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. - - ---------------------------------------------------------------- - - Notice that the above BSD-style license applies to this one file - (valgrind.h) only. The entire rest of Valgrind is licensed under - the terms of the GNU General Public License, version 2. See the - COPYING file in the source distribution for details. - - ---------------------------------------------------------------- -*/ - - -/* This file is for inclusion into client (your!) code. - - You can use these macros to manipulate and query Valgrind's - execution inside your own programs. - - The resulting executables will still run without Valgrind, just a - little bit more slowly than they otherwise would, but otherwise - unchanged. When not running on valgrind, each client request - consumes very few (eg. 7) instructions, so the resulting performance - loss is negligible unless you plan to execute client requests - millions of times per second. Nevertheless, if that is still a - problem, you can compile with the NVALGRIND symbol defined (gcc - -DNVALGRIND) so that client requests are not even compiled in. */ - -#ifndef __VALGRIND_H -#define __VALGRIND_H - - -/* ------------------------------------------------------------------ */ -/* VERSION NUMBER OF VALGRIND */ -/* ------------------------------------------------------------------ */ - -/* Specify Valgrind's version number, so that user code can - conditionally compile based on our version number. Note that these - were introduced at version 3.6 and so do not exist in version 3.5 - or earlier. The recommended way to use them to check for "version - X.Y or later" is (eg) - -#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ - && (__VALGRIND_MAJOR__ > 3 \ - || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) -*/ -#define __VALGRIND_MAJOR__ 3 -#define __VALGRIND_MINOR__ 6 - - -#include - -/* Nb: this file might be included in a file compiled with -ansi. So - we can't use C++ style "//" comments nor the "asm" keyword (instead - use "__asm__"). */ - -/* Derive some tags indicating what the target platform is. Note - that in this file we're using the compiler's CPP symbols for - identifying architectures, which are different to the ones we use - within the rest of Valgrind. Note, __powerpc__ is active for both - 32 and 64-bit PPC, whereas __powerpc64__ is only active for the - latter (on Linux, that is). - - Misc note: how to find out what's predefined in gcc by default: - gcc -Wp,-dM somefile.c -*/ -#undef PLAT_ppc64_aix5 -#undef PLAT_ppc32_aix5 -#undef PLAT_x86_darwin -#undef PLAT_amd64_darwin -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_arm_linux - -#if defined(_AIX) && defined(__64BIT__) -# define PLAT_ppc64_aix5 1 -#elif defined(_AIX) && !defined(__64BIT__) -# define PLAT_ppc32_aix5 1 -#elif defined(__APPLE__) && defined(__i386__) -# define PLAT_x86_darwin 1 -#elif defined(__APPLE__) && defined(__x86_64__) -# define PLAT_amd64_darwin 1 -#elif defined(__linux__) && defined(__i386__) -# define PLAT_x86_linux 1 -#elif defined(__linux__) && defined(__x86_64__) -# define PLAT_amd64_linux 1 -#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) -# define PLAT_ppc32_linux 1 -#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) -# define PLAT_ppc64_linux 1 -#elif defined(__linux__) && defined(__arm__) -# define PLAT_arm_linux 1 -#else -/* If we're not compiling for our target platform, don't generate - any inline asms. */ -# if !defined(NVALGRIND) -# define NVALGRIND 1 -# endif -#endif - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ -/* in here of use to end-users -- skip to the next section. */ -/* ------------------------------------------------------------------ */ - -#if defined(NVALGRIND) - -/* Define NVALGRIND to completely remove the Valgrind magic sequence - from the compiled code (analogous to NDEBUG's effects on - assert()) */ -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { \ - (_zzq_rlval) = (_zzq_default); \ - } - -#else /* ! NVALGRIND */ - -/* The following defines the magic code sequences which the JITter - spots and handles magically. Don't look too closely at them as - they will rot your brain. - - The assembly code sequences for all architectures is in this one - file. This is because this file must be stand-alone, and we don't - want to have multiple files. - - For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default - value gets put in the return slot, so that everything works when - this is executed not under Valgrind. Args are passed in a memory - block, and so there's no intrinsic limit to the number that could - be passed, but it's currently five. - - The macro args are: - _zzq_rlval result lvalue - _zzq_default default value (result returned when running on real CPU) - _zzq_request request code - _zzq_arg1..5 request params - - The other two macros are used to support function wrapping, and are - a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the - guest's NRADDR pseudo-register and whatever other information is - needed to safely run the call original from the wrapper: on - ppc64-linux, the R2 value at the divert point is also needed. This - information is abstracted into a user-visible type, OrigFn. - - VALGRIND_CALL_NOREDIR_* behaves the same as the following on the - guest, but guarantees that the branch instruction will not be - redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: - branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a - complete inline asm, since it needs to be combined with more magic - inline asm stuff to be useful. -*/ - -/* ------------------------- x86-{linux,darwin} ---------------- */ - -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "roll $3, %%edi ; roll $13, %%edi\n\t" \ - "roll $29, %%edi ; roll $19, %%edi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EDX = client_request ( %EAX ) */ \ - "xchgl %%ebx,%%ebx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %EAX = guest_NRADDR */ \ - "xchgl %%ecx,%%ecx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_EAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%EAX */ \ - "xchgl %%edx,%%edx\n\t" -#endif /* PLAT_x86_linux || PLAT_x86_darwin */ - -/* ------------------------ amd64-{linux,darwin} --------------- */ - -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ - "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - { volatile unsigned long long int _zzq_args[6]; \ - volatile unsigned long long int _zzq_result; \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RDX = client_request ( %RAX ) */ \ - "xchgq %%rbx,%%rbx" \ - : "=d" (_zzq_result) \ - : "a" (&_zzq_args[0]), "0" (_zzq_default) \ - : "cc", "memory" \ - ); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - volatile unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %RAX = guest_NRADDR */ \ - "xchgq %%rcx,%%rcx" \ - : "=a" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_CALL_NOREDIR_RAX \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* call-noredir *%RAX */ \ - "xchgq %%rdx,%%rdx\n\t" -#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[6]; \ - unsigned int _zzq_result; \ - unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 3,%1\n\t" /*default*/ \ - "mr 4,%2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" /*result*/ \ - : "=b" (_zzq_result) \ - : "b" (_zzq_default), "b" (_zzq_ptr) \ - : "cc", "memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "cc", "memory", "r3" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[6]; \ - register unsigned long long int _zzq_result __asm__("r3"); \ - register unsigned long long int* _zzq_ptr __asm__("r4"); \ - _zzq_args[0] = (unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1" \ - : "=r" (_zzq_result) \ - : "0" (_zzq_default), "r" (_zzq_ptr) \ - : "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr __asm__("r3"); \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4" \ - : "=r" (__addr) \ - : \ - : "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------- arm-linux ------------------------- */ - -#if defined(PLAT_arm_linux) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ - "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { volatile unsigned int _zzq_args[6]; \ - volatile unsigned int _zzq_result; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - __asm__ volatile("mov r3, %1\n\t" /*default*/ \ - "mov r4, %2\n\t" /*ptr*/ \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* R3 = client_request ( R4 ) */ \ - "orr r10, r10, r10\n\t" \ - "mov %0, r3" /*result*/ \ - : "=r" (_zzq_result) \ - : "r" (_zzq_default), "r" (&_zzq_args[0]) \ - : "cc","memory", "r3", "r4"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* R3 = guest_NRADDR */ \ - "orr r11, r11, r11\n\t" \ - "mov %0, r3" \ - : "=r" (__addr) \ - : \ - : "cc", "memory", "r3" \ - ); \ - _zzq_orig->nraddr = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R4 */ \ - "orr r12, r12, r12\n\t" - -#endif /* PLAT_arm_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -typedef - struct { - unsigned int nraddr; /* where's the code? */ - unsigned int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned int _zzq_args[7]; \ - register unsigned int _zzq_result; \ - register unsigned int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int)(_zzq_request); \ - _zzq_args[1] = (unsigned int)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "lwz 3, 24(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -typedef - struct { - unsigned long long int nraddr; /* where's the code? */ - unsigned long long int r2; /* what tocptr do we need? */ - } - OrigFn; - -#define __SPECIAL_INSTRUCTION_PREAMBLE \ - "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ - "rotldi 0,0,61 ; rotldi 0,0,51\n\t" - -#define VALGRIND_DO_CLIENT_REQUEST( \ - _zzq_rlval, _zzq_default, _zzq_request, \ - _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ - \ - { unsigned long long int _zzq_args[7]; \ - register unsigned long long int _zzq_result; \ - register unsigned long long int* _zzq_ptr; \ - _zzq_args[0] = (unsigned int long long)(_zzq_request); \ - _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \ - _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \ - _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \ - _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \ - _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \ - _zzq_args[6] = (unsigned int long long)(_zzq_default); \ - _zzq_ptr = _zzq_args; \ - __asm__ volatile("mr 4,%1\n\t" \ - "ld 3, 48(4)\n\t" \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = client_request ( %R4 ) */ \ - "or 1,1,1\n\t" \ - "mr %0,3" \ - : "=b" (_zzq_result) \ - : "b" (_zzq_ptr) \ - : "r3", "r4", "cc", "memory"); \ - _zzq_rlval = _zzq_result; \ - } - -#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ - { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ - register unsigned long long int __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR */ \ - "or 2,2,2\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->nraddr = __addr; \ - __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ - /* %R3 = guest_NRADDR_GPR2 */ \ - "or 4,4,4\n\t" \ - "mr %0,3" \ - : "=b" (__addr) \ - : \ - : "r3", "cc", "memory" \ - ); \ - _zzq_orig->r2 = __addr; \ - } - -#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - __SPECIAL_INSTRUCTION_PREAMBLE \ - /* branch-and-link-to-noredir *%R11 */ \ - "or 3,3,3\n\t" - -#endif /* PLAT_ppc64_aix5 */ - -/* Insert assembly code for other platforms here... */ - -#endif /* NVALGRIND */ - - -/* ------------------------------------------------------------------ */ -/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ -/* ugly. It's the least-worst tradeoff I can think of. */ -/* ------------------------------------------------------------------ */ - -/* This section defines magic (a.k.a appalling-hack) macros for doing - guaranteed-no-redirection macros, so as to get from function - wrappers to the functions they are wrapping. The whole point is to - construct standard call sequences, but to do the call itself with a - special no-redirect call pseudo-instruction that the JIT - understands and handles specially. This section is long and - repetitious, and I can't see a way to make it shorter. - - The naming scheme is as follows: - - CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} - - 'W' stands for "word" and 'v' for "void". Hence there are - different macros for calling arity 0, 1, 2, 3, 4, etc, functions, - and for each, the possibility of returning a word-typed result, or - no result. -*/ - -/* Use these to write the name of your wrapper. NOTE: duplicates - VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ - -/* Use an extra level of macroisation so as to ensure the soname/fnname - args are fully macro-expanded before pasting them together. */ -#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd - -#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ - VG_CONCAT4(_vgwZU_,soname,_,fnname) - -#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ - VG_CONCAT4(_vgwZZ_,soname,_,fnname) - -/* Use this macro from within a wrapper function to collect the - context (address and possibly other info) of the original function. - Once you have that you can then use it in one of the CALL_FN_ - macros. The type of the argument _lval is OrigFn. */ -#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) - -/* Derivatives of the main macros below, for calling functions - returning void. */ - -#define CALL_FN_v_v(fnptr) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_v(_junk,fnptr); } while (0) - -#define CALL_FN_v_W(fnptr, arg1) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_W(_junk,fnptr,arg1); } while (0) - -#define CALL_FN_v_WW(fnptr, arg1,arg2) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) - -#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) - -#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) - -#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) - -#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) - -#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ - do { volatile unsigned long _junk; \ - CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) - -/* ------------------------- x86-{linux,darwin} ---------------- */ - -#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) - -/* These regs are trashed by the hidden call. No need to mention eax - as gcc can already see that, plus causes gcc to bomb. */ -#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" - -/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $4, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $8, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $12, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $16, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $20, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $24, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $28, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $32, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $36, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $40, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $44, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "pushl 48(%%eax)\n\t" \ - "pushl 44(%%eax)\n\t" \ - "pushl 40(%%eax)\n\t" \ - "pushl 36(%%eax)\n\t" \ - "pushl 32(%%eax)\n\t" \ - "pushl 28(%%eax)\n\t" \ - "pushl 24(%%eax)\n\t" \ - "pushl 20(%%eax)\n\t" \ - "pushl 16(%%eax)\n\t" \ - "pushl 12(%%eax)\n\t" \ - "pushl 8(%%eax)\n\t" \ - "pushl 4(%%eax)\n\t" \ - "movl (%%eax), %%eax\n\t" /* target->%eax */ \ - VALGRIND_CALL_NOREDIR_EAX \ - "addl $48, %%esp\n" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_x86_linux || PLAT_x86_darwin */ - -/* ------------------------ amd64-{linux,darwin} --------------- */ - -#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) - -/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ - "rdi", "r8", "r9", "r10", "r11" - -/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned - long) == 8. */ - -/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ - macros. In order not to trash the stack redzone, we need to drop - %rsp by 128 before the hidden call, and restore afterwards. The - nastyness is that it is only by luck that the stack still appears - to be unwindable during the hidden call - since then the behaviour - of any routine using this macro does not match what the CFI data - says. Sigh. - - Why is this important? Imagine that a wrapper has a stack - allocated local, and passes to the hidden call, a pointer to it. - Because gcc does not know about the hidden call, it may allocate - that local in the redzone. Unfortunately the hidden call may then - trash it before it comes to use it. So we must step clear of the - redzone, for the duration of the hidden call, to make it safe. - - Probably the same problem afflicts the other redzone-style ABIs too - (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is - self describing (none of this CFI nonsense) so at least messing - with the stack pointer doesn't give a danger of non-unwindable - stack. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - "addq $128,%%rsp\n\t" \ - VALGRIND_CALL_NOREDIR_RAX \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $8, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $16, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $24, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $32, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $40, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "subq $128,%%rsp\n\t" \ - "pushq 96(%%rax)\n\t" \ - "pushq 88(%%rax)\n\t" \ - "pushq 80(%%rax)\n\t" \ - "pushq 72(%%rax)\n\t" \ - "pushq 64(%%rax)\n\t" \ - "pushq 56(%%rax)\n\t" \ - "movq 48(%%rax), %%r9\n\t" \ - "movq 40(%%rax), %%r8\n\t" \ - "movq 32(%%rax), %%rcx\n\t" \ - "movq 24(%%rax), %%rdx\n\t" \ - "movq 16(%%rax), %%rsi\n\t" \ - "movq 8(%%rax), %%rdi\n\t" \ - "movq (%%rax), %%rax\n\t" /* target->%rax */ \ - VALGRIND_CALL_NOREDIR_RAX \ - "addq $48, %%rsp\n" \ - "addq $128,%%rsp\n\t" \ - : /*out*/ "=a" (_res) \ - : /*in*/ "a" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ - -/* ------------------------ ppc32-linux ------------------------ */ - -#if defined(PLAT_ppc32_linux) - -/* This is useful for finding out about the on-stack stuff: - - extern int f9 ( int,int,int,int,int,int,int,int,int ); - extern int f10 ( int,int,int,int,int,int,int,int,int,int ); - extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); - extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); - - int g9 ( void ) { - return f9(11,22,33,44,55,66,77,88,99); - } - int g10 ( void ) { - return f10(11,22,33,44,55,66,77,88,99,110); - } - int g11 ( void ) { - return f11(11,22,33,44,55,66,77,88,99,110,121); - } - int g12 ( void ) { - return f12(11,22,33,44,55,66,77,88,99,110,121,132); - } -*/ - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc32-linux, - sizeof(unsigned long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-16\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,16\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)arg1; \ - _argvec[2] = (unsigned long)arg2; \ - _argvec[3] = (unsigned long)arg3; \ - _argvec[4] = (unsigned long)arg4; \ - _argvec[5] = (unsigned long)arg5; \ - _argvec[6] = (unsigned long)arg6; \ - _argvec[7] = (unsigned long)arg7; \ - _argvec[8] = (unsigned long)arg8; \ - _argvec[9] = (unsigned long)arg9; \ - _argvec[10] = (unsigned long)arg10; \ - _argvec[11] = (unsigned long)arg11; \ - _argvec[12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "addi 1,1,-32\n\t" \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,20(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,16(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,12(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,8(1)\n\t" \ - /* args1-8 */ \ - "lwz 3,4(11)\n\t" /* arg1->r3 */ \ - "lwz 4,8(11)\n\t" \ - "lwz 5,12(11)\n\t" \ - "lwz 6,16(11)\n\t" /* arg4->r6 */ \ - "lwz 7,20(11)\n\t" \ - "lwz 8,24(11)\n\t" \ - "lwz 9,28(11)\n\t" \ - "lwz 10,32(11)\n\t" /* arg8->r10 */ \ - "lwz 11,0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "addi 1,1,32\n\t" \ - "mr %0,3" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_linux */ - -/* ------------------------ ppc64-linux ------------------------ */ - -#if defined(PLAT_ppc64_linux) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)" /* restore tocptr */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-128\n\t" /* expand stack frame */ \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,128" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "addi 1,1,-144\n\t" /* expand stack frame */ \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - "addi 1,1,144" /* restore frame */ \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_linux */ - -/* ------------------------- arm-linux ------------------------- */ - -#if defined(PLAT_arm_linux) - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14" - -/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[1]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[2]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[4]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0\n" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[5]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - __asm__ volatile( \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[6]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "push {r0} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #4 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[7]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "push {r0, r1} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #8 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[8]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "push {r0, r1, r2} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #12 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[9]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "push {r0, r1, r2, r3} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #16 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[10]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - __asm__ volatile( \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #20 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[11]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - __asm__ volatile( \ - "ldr r0, [%1, #40] \n\t" \ - "push {r0} \n\t" \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #24 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[12]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - __asm__ volatile( \ - "ldr r0, [%1, #40] \n\t" \ - "ldr r1, [%1, #44] \n\t" \ - "push {r0, r1} \n\t" \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #28 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ - arg6,arg7,arg8,arg9,arg10, \ - arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[13]; \ - volatile unsigned long _res; \ - _argvec[0] = (unsigned long)_orig.nraddr; \ - _argvec[1] = (unsigned long)(arg1); \ - _argvec[2] = (unsigned long)(arg2); \ - _argvec[3] = (unsigned long)(arg3); \ - _argvec[4] = (unsigned long)(arg4); \ - _argvec[5] = (unsigned long)(arg5); \ - _argvec[6] = (unsigned long)(arg6); \ - _argvec[7] = (unsigned long)(arg7); \ - _argvec[8] = (unsigned long)(arg8); \ - _argvec[9] = (unsigned long)(arg9); \ - _argvec[10] = (unsigned long)(arg10); \ - _argvec[11] = (unsigned long)(arg11); \ - _argvec[12] = (unsigned long)(arg12); \ - __asm__ volatile( \ - "ldr r0, [%1, #40] \n\t" \ - "ldr r1, [%1, #44] \n\t" \ - "ldr r2, [%1, #48] \n\t" \ - "push {r0, r1, r2} \n\t" \ - "ldr r0, [%1, #20] \n\t" \ - "ldr r1, [%1, #24] \n\t" \ - "ldr r2, [%1, #28] \n\t" \ - "ldr r3, [%1, #32] \n\t" \ - "ldr r4, [%1, #36] \n\t" \ - "push {r0, r1, r2, r3, r4} \n\t" \ - "ldr r0, [%1, #4] \n\t" \ - "ldr r1, [%1, #8] \n\t" \ - "ldr r2, [%1, #12] \n\t" \ - "ldr r3, [%1, #16] \n\t" \ - "ldr r4, [%1] \n\t" /* target->r4 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ - "add sp, sp, #32 \n\t" \ - "mov %0, r0" \ - : /*out*/ "=r" (_res) \ - : /*in*/ "0" (&_argvec[0]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_arm_linux */ - -/* ------------------------ ppc32-aix5 ------------------------- */ - -#if defined(PLAT_ppc32_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "lwz 3," #_n_fr "(1)\n\t" \ - "stw 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned - long) == 4. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(64) \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(64) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "stw 2,-8(11)\n\t" /* save tocptr */ \ - "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(72) \ - /* arg12 */ \ - "lwz 3,48(11)\n\t" \ - "stw 3,68(1)\n\t" \ - /* arg11 */ \ - "lwz 3,44(11)\n\t" \ - "stw 3,64(1)\n\t" \ - /* arg10 */ \ - "lwz 3,40(11)\n\t" \ - "stw 3,60(1)\n\t" \ - /* arg9 */ \ - "lwz 3,36(11)\n\t" \ - "stw 3,56(1)\n\t" \ - /* args1-8 */ \ - "lwz 3, 4(11)\n\t" /* arg1->r3 */ \ - "lwz 4, 8(11)\n\t" /* arg2->r4 */ \ - "lwz 5, 12(11)\n\t" /* arg3->r5 */ \ - "lwz 6, 16(11)\n\t" /* arg4->r6 */ \ - "lwz 7, 20(11)\n\t" /* arg5->r7 */ \ - "lwz 8, 24(11)\n\t" /* arg6->r8 */ \ - "lwz 9, 28(11)\n\t" /* arg7->r9 */ \ - "lwz 10, 32(11)\n\t" /* arg8->r10 */ \ - "lwz 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "lwz 2,-8(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(72) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc32_aix5 */ - -/* ------------------------ ppc64-aix5 ------------------------- */ - -#if defined(PLAT_ppc64_aix5) - -/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ - -/* These regs are trashed by the hidden call. */ -#define __CALLER_SAVED_REGS \ - "lr", "ctr", "xer", \ - "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ - "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ - "r11", "r12", "r13" - -/* Expand the stack frame, copying enough info that unwinding - still works. Trashes r3. */ - -#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \ - "addi 1,1,-" #_n_fr "\n\t" \ - "ld 3," #_n_fr "(1)\n\t" \ - "std 3,0(1)\n\t" - -#define VG_CONTRACT_FRAME_BY(_n_fr) \ - "addi 1,1," #_n_fr "\n\t" - -/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned - long) == 8. */ - -#define CALL_FN_W_v(lval, orig) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+0]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_W(lval, orig, arg1) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+1]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WW(lval, orig, arg1,arg2) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+2]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+3]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+4]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+5]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+6]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+7]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+8]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+9]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+10]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(128) \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(128) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+11]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ - arg7,arg8,arg9,arg10,arg11,arg12) \ - do { \ - volatile OrigFn _orig = (orig); \ - volatile unsigned long _argvec[3+12]; \ - volatile unsigned long _res; \ - /* _argvec[0] holds current r2 across the call */ \ - _argvec[1] = (unsigned long)_orig.r2; \ - _argvec[2] = (unsigned long)_orig.nraddr; \ - _argvec[2+1] = (unsigned long)arg1; \ - _argvec[2+2] = (unsigned long)arg2; \ - _argvec[2+3] = (unsigned long)arg3; \ - _argvec[2+4] = (unsigned long)arg4; \ - _argvec[2+5] = (unsigned long)arg5; \ - _argvec[2+6] = (unsigned long)arg6; \ - _argvec[2+7] = (unsigned long)arg7; \ - _argvec[2+8] = (unsigned long)arg8; \ - _argvec[2+9] = (unsigned long)arg9; \ - _argvec[2+10] = (unsigned long)arg10; \ - _argvec[2+11] = (unsigned long)arg11; \ - _argvec[2+12] = (unsigned long)arg12; \ - __asm__ volatile( \ - "mr 11,%1\n\t" \ - VG_EXPAND_FRAME_BY_trashes_r3(512) \ - "std 2,-16(11)\n\t" /* save tocptr */ \ - "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ - VG_EXPAND_FRAME_BY_trashes_r3(144) \ - /* arg12 */ \ - "ld 3,96(11)\n\t" \ - "std 3,136(1)\n\t" \ - /* arg11 */ \ - "ld 3,88(11)\n\t" \ - "std 3,128(1)\n\t" \ - /* arg10 */ \ - "ld 3,80(11)\n\t" \ - "std 3,120(1)\n\t" \ - /* arg9 */ \ - "ld 3,72(11)\n\t" \ - "std 3,112(1)\n\t" \ - /* args1-8 */ \ - "ld 3, 8(11)\n\t" /* arg1->r3 */ \ - "ld 4, 16(11)\n\t" /* arg2->r4 */ \ - "ld 5, 24(11)\n\t" /* arg3->r5 */ \ - "ld 6, 32(11)\n\t" /* arg4->r6 */ \ - "ld 7, 40(11)\n\t" /* arg5->r7 */ \ - "ld 8, 48(11)\n\t" /* arg6->r8 */ \ - "ld 9, 56(11)\n\t" /* arg7->r9 */ \ - "ld 10, 64(11)\n\t" /* arg8->r10 */ \ - "ld 11, 0(11)\n\t" /* target->r11 */ \ - VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ - "mr 11,%1\n\t" \ - "mr %0,3\n\t" \ - "ld 2,-16(11)\n\t" /* restore tocptr */ \ - VG_CONTRACT_FRAME_BY(144) \ - VG_CONTRACT_FRAME_BY(512) \ - : /*out*/ "=r" (_res) \ - : /*in*/ "r" (&_argvec[2]) \ - : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ - ); \ - lval = (__typeof__(lval)) _res; \ - } while (0) - -#endif /* PLAT_ppc64_aix5 */ - - -/* ------------------------------------------------------------------ */ -/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ -/* */ -/* ------------------------------------------------------------------ */ - -/* Some request codes. There are many more of these, but most are not - exposed to end-user view. These are the public ones, all of the - form 0x1000 + small_number. - - Core ones are in the range 0x00000000--0x0000ffff. The non-public - ones start at 0x2000. -*/ - -/* These macros are used by tools -- they must be public, but don't - embed them into other programs. */ -#define VG_USERREQ_TOOL_BASE(a,b) \ - ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) -#define VG_IS_TOOL_USERREQ(a, b, v) \ - (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) - -/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! - This enum comprises an ABI exported by Valgrind to programs - which use client requests. DO NOT CHANGE THE ORDER OF THESE - ENTRIES, NOR DELETE ANY -- add new ones at the end. */ -typedef - enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, - VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, - - /* These allow any function to be called from the simulated - CPU but run on the real CPU. Nb: the first arg passed to - the function is always the ThreadId of the running - thread! So CLIENT_CALL0 actually requires a 1 arg - function, etc. */ - VG_USERREQ__CLIENT_CALL0 = 0x1101, - VG_USERREQ__CLIENT_CALL1 = 0x1102, - VG_USERREQ__CLIENT_CALL2 = 0x1103, - VG_USERREQ__CLIENT_CALL3 = 0x1104, - - /* Can be useful in regression testing suites -- eg. can - send Valgrind's output to /dev/null and still count - errors. */ - VG_USERREQ__COUNT_ERRORS = 0x1201, - - /* These are useful and can be interpreted by any tool that - tracks malloc() et al, by using vg_replace_malloc.c. */ - VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, - VG_USERREQ__FREELIKE_BLOCK = 0x1302, - /* Memory pool support. */ - VG_USERREQ__CREATE_MEMPOOL = 0x1303, - VG_USERREQ__DESTROY_MEMPOOL = 0x1304, - VG_USERREQ__MEMPOOL_ALLOC = 0x1305, - VG_USERREQ__MEMPOOL_FREE = 0x1306, - VG_USERREQ__MEMPOOL_TRIM = 0x1307, - VG_USERREQ__MOVE_MEMPOOL = 0x1308, - VG_USERREQ__MEMPOOL_CHANGE = 0x1309, - VG_USERREQ__MEMPOOL_EXISTS = 0x130a, - - /* Allow printfs to valgrind log. */ - /* The first two pass the va_list argument by value, which - assumes it is the same size as or smaller than a UWord, - which generally isn't the case. Hence are deprecated. - The second two pass the vargs by reference and so are - immune to this problem. */ - /* both :: char* fmt, va_list vargs (DEPRECATED) */ - VG_USERREQ__PRINTF = 0x1401, - VG_USERREQ__PRINTF_BACKTRACE = 0x1402, - /* both :: char* fmt, va_list* vargs */ - VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, - VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, - - /* Stack support. */ - VG_USERREQ__STACK_REGISTER = 0x1501, - VG_USERREQ__STACK_DEREGISTER = 0x1502, - VG_USERREQ__STACK_CHANGE = 0x1503, - - /* Wine support */ - VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601 - } Vg_ClientRequest; - -#if !defined(__GNUC__) -# define __extension__ /* */ -#endif - -/* Returns the number of Valgrinds this code is running under. That - is, 0 if running natively, 1 if running under Valgrind, 2 if - running under Valgrind which is running under another Valgrind, - etc. */ -#define RUNNING_ON_VALGRIND __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ - VG_USERREQ__RUNNING_ON_VALGRIND, \ - 0, 0, 0, 0, 0); \ - _qzz_res; \ - }) - - -/* Discard translation of code in the range [_qzz_addr .. _qzz_addr + - _qzz_len - 1]. Useful if you are debugging a JITter or some such, - since it provides a way to make sure valgrind will retranslate the - invalidated area. Returns no value. */ -#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DISCARD_TRANSLATIONS, \ - _qzz_addr, _qzz_len, 0, 0, 0); \ - } - - -/* These requests are for getting Valgrind itself to print something. - Possibly with a backtrace. This is a really ugly hack. The return value - is the number of characters printed, excluding the "**** " part at the - start and the backtrace (if present). */ - -#if defined(NVALGRIND) - -# define VALGRIND_PRINTF(...) -# define VALGRIND_PRINTF_BACKTRACE(...) - -#else /* NVALGRIND */ - -/* Modern GCC will optimize the static routine out if unused, - and unused attribute will shut down warnings about it. */ -static int VALGRIND_PRINTF(const char *format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -static int -VALGRIND_PRINTF(const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, - VG_USERREQ__PRINTF_VALIST_BY_REF, - (unsigned long)format, - (unsigned long)&vargs, - 0, 0, 0); - va_end(vargs); - return (int)_qzz_res; -} - -static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) - __attribute__((format(__printf__, 1, 2), __unused__)); -static int -VALGRIND_PRINTF_BACKTRACE(const char *format, ...) -{ - unsigned long _qzz_res; - va_list vargs; - va_start(vargs, format); - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, - VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, - (unsigned long)format, - (unsigned long)&vargs, - 0, 0, 0); - va_end(vargs); - return (int)_qzz_res; -} - -#endif /* NVALGRIND */ - - -/* These requests allow control to move from the simulated CPU to the - real CPU, calling an arbitary function. - - Note that the current ThreadId is inserted as the first argument. - So this call: - - VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) - - requires f to have this signature: - - Word f(Word tid, Word arg1, Word arg2) - - where "Word" is a word-sized type. - - Note that these client requests are not entirely reliable. For example, - if you call a function with them that subsequently calls printf(), - there's a high chance Valgrind will crash. Generally, your prospects of - these working are made higher if the called function does not refer to - any global variables, and does not refer to any libc or other functions - (printf et al). Any kind of entanglement with libc or dynamic linking is - likely to have a bad outcome, for tricky reasons which we've grappled - with a lot in the past. -*/ -#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL0, \ - _qyy_fn, \ - 0, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL1, \ - _qyy_fn, \ - _qyy_arg1, 0, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL2, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, 0, 0); \ - _qyy_res; \ - }) - -#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ - __extension__ \ - ({unsigned long _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__CLIENT_CALL3, \ - _qyy_fn, \ - _qyy_arg1, _qyy_arg2, \ - _qyy_arg3, 0); \ - _qyy_res; \ - }) - - -/* Counts the number of errors that have been recorded by a tool. Nb: - the tool must record the errors with VG_(maybe_record_error)() or - VG_(unique_error)() for them to be counted. */ -#define VALGRIND_COUNT_ERRORS \ - __extension__ \ - ({unsigned int _qyy_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ - VG_USERREQ__COUNT_ERRORS, \ - 0, 0, 0, 0, 0); \ - _qyy_res; \ - }) - -/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing - when heap blocks are allocated in order to give accurate results. This - happens automatically for the standard allocator functions such as - malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, - delete[], etc. - - But if your program uses a custom allocator, this doesn't automatically - happen, and Valgrind will not do as well. For example, if you allocate - superblocks with mmap() and then allocates chunks of the superblocks, all - Valgrind's observations will be at the mmap() level and it won't know that - the chunks should be considered separate entities. In Memcheck's case, - that means you probably won't get heap block overrun detection (because - there won't be redzones marked as unaddressable) and you definitely won't - get any leak detection. - - The following client requests allow a custom allocator to be annotated so - that it can be handled accurately by Valgrind. - - VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated - by a malloc()-like function. For Memcheck (an illustrative case), this - does two things: - - - It records that the block has been allocated. This means any addresses - within the block mentioned in error messages will be - identified as belonging to the block. It also means that if the block - isn't freed it will be detected by the leak checker. - - - It marks the block as being addressable and undefined (if 'is_zeroed' is - not set), or addressable and defined (if 'is_zeroed' is set). This - controls how accesses to the block by the program are handled. - - 'addr' is the start of the usable block (ie. after any - redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator - can apply redzones -- these are blocks of padding at the start and end of - each block. Adding redzones is recommended as it makes it much more likely - Valgrind will spot block overruns. `is_zeroed' indicates if the memory is - zeroed (or filled with another predictable value), as is the case for - calloc(). - - VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a - heap block -- that will be used by the client program -- is allocated. - It's best to put it at the outermost level of the allocator if possible; - for example, if you have a function my_alloc() which calls - internal_alloc(), and the client request is put inside internal_alloc(), - stack traces relating to the heap block will contain entries for both - my_alloc() and internal_alloc(), which is probably not what you want. - - For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out - custom blocks from within a heap block, B, that has been allocated with - malloc/calloc/new/etc, then block B will be *ignored* during leak-checking - -- the custom blocks will take precedence. - - VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For - Memcheck, it does two things: - - - It records that the block has been deallocated. This assumes that the - block was annotated as having been allocated via - VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. - - - It marks the block as being unaddressable. - - VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a - heap block is deallocated. - - In many cases, these two client requests will not be enough to get your - allocator working well with Memcheck. More specifically, if your allocator - writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call - will be necessary to mark the memory as addressable just before the zeroing - occurs, otherwise you'll get a lot of invalid write errors. For example, - you'll need to do this if your allocator recycles freed blocks, but it - zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). - Alternatively, if your allocator reuses freed blocks for allocator-internal - data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. - - Really, what's happening is a blurring of the lines between the client - program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the - memory should be considered unaddressable to the client program, but the - allocator knows more than the rest of the client program and so may be able - to safely access it. Extra client requests are necessary for Valgrind to - understand the distinction between the allocator and the rest of the - program. - - Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it - has to be emulated with MALLOCLIKE/FREELIKE and memory copying. - - Ignored if addr == 0. -*/ -#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MALLOCLIKE_BLOCK, \ - addr, sizeB, rzB, is_zeroed, 0); \ - } - -/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. - Ignored if addr == 0. -*/ -#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__FREELIKE_BLOCK, \ - addr, rzB, 0, 0, 0); \ - } - -/* Create a memory pool. */ -#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__CREATE_MEMPOOL, \ - pool, rzB, is_zeroed, 0, 0); \ - } - -/* Destroy a memory pool. */ -#define VALGRIND_DESTROY_MEMPOOL(pool) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__DESTROY_MEMPOOL, \ - pool, 0, 0, 0, 0); \ - } - -/* Associate a piece of memory with a memory pool. */ -#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_ALLOC, \ - pool, addr, size, 0, 0); \ - } - -/* Disassociate a piece of memory from a memory pool. */ -#define VALGRIND_MEMPOOL_FREE(pool, addr) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_FREE, \ - pool, addr, 0, 0, 0); \ - } - -/* Disassociate any pieces outside a particular range. */ -#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_TRIM, \ - pool, addr, size, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MOVE_MEMPOOL, \ - poolA, poolB, 0, 0, 0); \ - } - -/* Resize and/or move a piece associated with a memory pool. */ -#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_CHANGE, \ - pool, addrA, addrB, size, 0); \ - } - -/* Return 1 if a mempool exists, else 0. */ -#define VALGRIND_MEMPOOL_EXISTS(pool) \ - __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__MEMPOOL_EXISTS, \ - pool, 0, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Mark a piece of memory as being a stack. Returns a stack id. */ -#define VALGRIND_STACK_REGISTER(start, end) \ - __extension__ \ - ({unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_REGISTER, \ - start, end, 0, 0, 0); \ - _qzz_res; \ - }) - -/* Unmark the piece of memory associated with a stack id as being a - stack. */ -#define VALGRIND_STACK_DEREGISTER(id) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_DEREGISTER, \ - id, 0, 0, 0, 0); \ - } - -/* Change the start and end address of the stack id. */ -#define VALGRIND_STACK_CHANGE(id, start, end) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__STACK_CHANGE, \ - id, start, end, 0, 0); \ - } - -/* Load PDB debug info for Wine PE image_map. */ -#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ - {unsigned int _qzz_res; \ - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ - VG_USERREQ__LOAD_PDB_DEBUGINFO, \ - fd, ptr, total_size, delta, 0); \ - } - - -#undef PLAT_x86_linux -#undef PLAT_amd64_linux -#undef PLAT_ppc32_linux -#undef PLAT_ppc64_linux -#undef PLAT_arm_linux -#undef PLAT_ppc32_aix5 -#undef PLAT_ppc64_aix5 - -#endif /* __VALGRIND_H */