void BlockSyntaxNode::addSuccessors(SyntaxNode *root, std::vector<SyntaxNode *> &successors) { for (unsigned i = 0; i < statements.size(); i++) { if (statements[i]->isBlock()) { //BlockSyntaxNode *b = (BlockSyntaxNode*)statements[i]; // can move previous statements into this block if (i > 0) { std::cerr << "successor: move previous statement into block" << std::endl; SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); BlockSyntaxNode *b1 = (BlockSyntaxNode *)this->clone(); BlockSyntaxNode *nb = (BlockSyntaxNode *)b1->getStatement(i); b1 = (BlockSyntaxNode *)b1->replace(statements[i - 1], NULL); nb->prependStatement(statements[i - 1]->clone()); n = n->replace(this, b1); successors.push_back(n); //PRINT_BEFORE_AFTER } } else { if (statements.size() != 1) { // can replace statement with a block containing that statement std::cerr << "successor: replace statement with a block containing the statement" << std::endl; BlockSyntaxNode *b = new BlockSyntaxNode(); b->addStatement(statements[i]->clone()); SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); n = n->replace(statements[i], b); successors.push_back(n); //PRINT_BEFORE_AFTER } } // "jump over" style of if-then if (i < statements.size() - 2 && statements[i]->isBranch()) { SyntaxNode *b = statements[i]; if (b->getOutEdge(root, 0) == statements[i + 2] && (statements[i + 1]->getOutEdge(root, 0) == statements[i + 2] || statements[i + 1]->endsWithGoto())) { std::cerr << "successor: jump over style if then" << std::endl; BlockSyntaxNode *b1 = (BlockSyntaxNode *)this->clone(); b1 = (BlockSyntaxNode *)b1->replace(statements[i + 1], NULL); IfThenSyntaxNode *nif = new IfThenSyntaxNode(); Exp *cond = b->getBB()->getCond(); cond = new Unary(opLNot, cond->clone()); cond = cond->simplify(); nif->setCond(cond); nif->setThen(statements[i + 1]->clone()); nif->setBB(b->getBB()); b1->setStatement(i, nif); SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); n = n->replace(this, b1); successors.push_back(n); //PRINT_BEFORE_AFTER } } // if then else if (i < statements.size() - 2 && statements[i]->isBranch()) { SyntaxNode *tThen = statements[i]->getOutEdge(root, 0); SyntaxNode *tElse = statements[i]->getOutEdge(root, 1); assert(tThen && tElse); if (((tThen == statements[i + 2] && tElse == statements[i + 1]) || (tThen == statements[i + 1] && tElse == statements[i + 2])) && tThen->getNumOutEdges() == 1 && tElse->getNumOutEdges() == 1) { SyntaxNode *else_out = tElse->getOutEdge(root, 0); SyntaxNode *then_out = tThen->getOutEdge(root, 0); if (else_out == then_out) { std::cerr << "successor: if then else" << std::endl; SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); n = n->replace(tThen, NULL); n = n->replace(tElse, NULL); IfThenElseSyntaxNode *nif = new IfThenElseSyntaxNode(); nif->setCond(statements[i]->getBB()->getCond()->clone()); nif->setBB(statements[i]->getBB()); nif->setThen(tThen->clone()); nif->setElse(tElse->clone()); n = n->replace(statements[i], nif); successors.push_back(n); //PRINT_BEFORE_AFTER } } } // pretested loop if (i < statements.size() - 2 && statements[i]->isBranch()) { SyntaxNode *tBody = statements[i]->getOutEdge(root, 0); SyntaxNode *tFollow = statements[i]->getOutEdge(root, 1); assert(tBody && tFollow); if (tBody == statements[i + 1] && tFollow == statements[i + 2] && tBody->getNumOutEdges() == 1 && tBody->getOutEdge(root, 0) == statements[i]) { std::cerr << "successor: pretested loop" << std::endl; SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); n = n->replace(tBody, NULL); PretestedLoopSyntaxNode *nloop = new PretestedLoopSyntaxNode(); nloop->setCond(statements[i]->getBB()->getCond()->clone()); nloop->setBB(statements[i]->getBB()); nloop->setBody(tBody->clone()); n = n->replace(statements[i], nloop); successors.push_back(n); //PRINT_BEFORE_AFTER } } // posttested loop if (i > 0 && i < statements.size() - 1 && statements[i]->isBranch()) { SyntaxNode *tBody = statements[i]->getOutEdge(root, 0); SyntaxNode *tFollow = statements[i]->getOutEdge(root, 1); assert(tBody && tFollow); if (tBody == statements[i - 1] && tFollow == statements[i + 1] && tBody->getNumOutEdges() == 1 && tBody->getOutEdge(root, 0) == statements[i]) { std::cerr << "successor: posttested loop" << std::endl; SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); n = n->replace(tBody, NULL); PostTestedLoopSyntaxNode *nloop = new PostTestedLoopSyntaxNode(); nloop->setCond(statements[i]->getBB()->getCond()->clone()); nloop->setBB(statements[i]->getBB()); nloop->setBody(tBody->clone()); n = n->replace(statements[i], nloop); successors.push_back(n); //PRINT_BEFORE_AFTER } } // infinite loop if (statements[i]->getNumOutEdges() == 1 && statements[i]->getOutEdge(root, 0) == statements[i]) { std::cerr << "successor: infinite loop" << std::endl; SyntaxNode *n = root->clone(); n->setDepth(root->getDepth() + 1); InfiniteLoopSyntaxNode *nloop = new InfiniteLoopSyntaxNode(); nloop->setBody(statements[i]->clone()); n = n->replace(statements[i], nloop); successors.push_back(n); PRINT_BEFORE_AFTER } statements[i]->addSuccessors(root, successors); }
int BlockSyntaxNode::evaluate(SyntaxNode *root) { #if DEBUG_EVAL if (this == root) std::cerr << "begin eval =============" << std::endl; #endif if (pbb) return 1; int n = 1; if (statements.size() == 1) { SyntaxNode *out = statements[0]->getOutEdge(root, 0); if (out->getBB() != NULL && out->getBB()->getNumInEdges() > 1) { #if DEBUG_EVAL std::cerr << "add 15" << std::endl; #endif n += 15; } else { #if DEBUG_EVAL std::cerr << "add 30" << std::endl; #endif n += 30; } } for (unsigned i = 0; i < statements.size(); i++) { n += statements[i]->evaluate(root); if (statements[i]->isGoto()) { if (i != statements.size() - 1) { #if DEBUG_EVAL std::cerr << "add 100" << std::endl; #endif n += 100; } else { #if DEBUG_EVAL std::cerr << "add 50" << std::endl; #endif n += 50; } } else if (statements[i]->isBranch()) { SyntaxNode *loop = root->getEnclosingLoop(this); std::cerr << "branch " << statements[i]->getNumber() << " not in loop" << std::endl; if (loop) { std::cerr << "branch " << statements[i]->getNumber() << " in loop " << loop->getNumber() << std::endl; // this is a bit C specific SyntaxNode *out = loop->getOutEdge(root, 0); if (out && statements[i]->getOutEdge(root, 0) == out) { std::cerr << "found break" << std::endl; n += 10; } if (statements[i]->getOutEdge(root, 0) == loop) { std::cerr << "found continue" << std::endl; n += 10; } } else { #if DEBUG_EVAL std::cerr << "add 50" << std::endl; #endif n += 50; } } else if (i < statements.size() - 1 && statements[i]->getOutEdge(root, 0) != statements[i + 1]) { #if DEBUG_EVAL std::cerr << "add 25" << std::endl; std::cerr << statements[i]->getNumber() << " -> " << statements[i]->getOutEdge(root, 0)->getNumber() << " not " << statements[i + 1]->getNumber() << std::endl; #endif n += 25; } } #if DEBUG_EVAL if (this == root) std::cerr << "end eval = " << n << " =============" << std::endl; #endif return n; }