Example #1
0
// True if any descendants are arrays.
bool containsArrayOps(const ASTNode& n)
{

  NodeIterator ni(n, n.GetSTPMgr()->ASTUndefined, *n.GetSTPMgr());
  ASTNode current;
  while ((current = ni.next()) != ni.end())
    if (current.GetIndexWidth() > 0)
      return true;

  return false;
}
Example #2
0
void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet, bool smtlib1)
{
  const Kind kind = n.GetKind();

  if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE)
    return;

  const ASTVec& c = n.GetChildren();
  for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
       it++)
  {
    const ASTNode& ccc = *it;

    const Kind k = ccc.GetKind();
    if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE)
      continue;

    if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end())
    {
      // If branch: if *it is not in NodeSet then,
      //
      // 1. add it to NodeSet
      //
      // 2. Letize its childNodes
      PLPrintNodeSet.insert(ccc);
      LetizeNode(ccc, PLPrintNodeSet, smtlib1);
    }
    else
    {
      // 0. Else branch: Node has been seen before
      //
      // 1. Check if the node has a corresponding letvar in the
      // 1. NodeLetVarMap.
      //
      // 2. if no, then create a new var and add it to the
      // 2. NodeLetVarMap
      if ((!smtlib1 || ccc.GetType() == BITVECTOR_TYPE) &&
          NodeLetVarMap.find(ccc) == NodeLetVarMap.end())
      {
        // Create a new symbol. Get some name. if it conflicts with a
        // declared name, too bad.
        int sz = NodeLetVarMap.size();
        std::ostringstream oss;
        oss << "?let_k_" << sz;

        ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol(
            oss.str().c_str(), n.GetIndexWidth(), n.GetValueWidth());
        /* If for some reason the variable being created here is
         * already declared by the user then the printed output will
         * not be a legal input to the system. too bad. I refuse to
         * check for this.  [Vijay is the author of this comment.]
         */

        NodeLetVarMap[ccc] = CurrentSymbol;
        std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc);
        NodeLetVarVec.push_back(node_letvar_pair);
      }
    }
  }
} // end of LetizeNode()
Example #3
0
  void outputBitVecSMTLIB2(const ASTNode n, ostream& os)
  {
	const Kind k = n.GetKind();
    const ASTVec &c = n.GetChildren();
    ASTNode op;

    if (BITVECTOR == k)
      {
        op = c[0];
      }
    else if (BVCONST == k)
      {
        op = n;
      }
    else
      FatalError("nsadfsdaf");

    // CONSTANTBV::BitVector_to_Dec returns a signed representation by default.
    // Prepend with zero to convert to unsigned.

    os << "(_ bv";
	CBV unsign = CONSTANTBV::BitVector_Concat(
			n.GetSTPMgr()->CreateZeroConst(1).GetBVConst(), op.GetBVConst());
    unsigned char * str = CONSTANTBV::BitVector_to_Dec(unsign);
    CONSTANTBV::BitVector_Destroy(unsign);
    os << str << " " << op.GetValueWidth() << ")";
    CONSTANTBV::BitVector_Dispose(str);
  }
    // If the bits are totally fixed, then return a new matching ASTNode.
    ASTNode
    bitsToNode(const ASTNode& node, const FixedBits& bits)
    {
      ASTNode result;
      STPMgr & beev = *node.GetSTPMgr();

      assert (bits.isTotallyFixed());
      assert (!node.isConstant()); // Peformance. Shouldn't waste time calling it on constants.

      if (node.GetType() == BOOLEAN_TYPE)
        {
          if (bits.getValue(0))
            {
              result = beev.CreateNode(TRUE);
            }
          else
            {
              result = beev.CreateNode(FALSE);
            }
        }
      else if (node.GetType() == BITVECTOR_TYPE)
        {
          result = beev.CreateBVConst(bits.GetBVConst(), node.GetValueWidth());
        }
      else
        FatalError("sadf234s");

      assert(result.isConstant());
      return result;
    }
  Result dispatchToMaximallyPrecise(const Kind k, vector<FixedBits*>& children,
      FixedBits& output, const ASTNode n)
    {
  #if WITHCBITP

      Signature signature;
      signature.kind = k;

      vector<FixedBits> childrenCopy;

      for (int i = 0; i < (int) children.size(); i++)
      childrenCopy.push_back(*(children[i]));
      FixedBits outputCopy(output);

      if (k == BVMULT)
        {
          // We've got some of multiply already implemented. So help it out by getting some done first.
          Result r = bvMultiplyBothWays(children, output, n.GetSTPMgr());
          if (CONFLICT == r)
          return CONFLICT;
        }

      bool bad = maxPrecision(children, output, k, n.GetSTPMgr());

      if (bad)
      return CONFLICT;

      if (!FixedBits::equals(outputCopy, output))
      return CHANGED;

      for (int i = 0; i < (int) children.size(); i++)
        {
          if (!FixedBits::equals(*(children[i]), childrenCopy[i]))
          return CHANGED;
        }

  #endif
      return NOT_IMPLEMENTED;
    }
    // Propagates. No writing in of values. Doesn't assume the top is true.
    ConstantBitPropagation::ConstantBitPropagation(BEEV::Simplifier* _sm, NodeFactory* _nf,const ASTNode & top)
    {
      assert (BOOLEAN_TYPE == top.GetType());
      assert (top.GetSTPMgr()->UserFlags.bitConstantProp_flag);

      status = NO_CHANGE;
      simplifier = _sm;
      nf = _nf;
      fixedMap = new NodeToFixedBitsMap(1000); // better to use the function that returns the number of nodes.. whatever that is.
      workList = new WorkList(top);
      dependents = new Dependencies(top); // List of the parents of a node.
      msm = new MultiplicationStatsMap();


      // not fixing the topnode.
      propagate();

      if (debug_cBitProp_messages)
        {
          cerr << "status:" << status <<endl;
          cerr << "ended propagation" << endl;
          printNodeWithFixings();
        }

      // is there are good reason to clear out some of them??
#if 0
      // remove constants, and things with nothing fixed.
      NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it =
          fixedMap->map->begin();
      NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it_end =
          fixedMap->map->end();
      while (it != it_end)
        {
          // No constants, nothing completely unfixed.
          if (  (it->second)->countFixed() == 0 )
            {
              delete it->second;
              // making this a reference causes reading from freed memory.
              const ASTNode n = it->first;
              it++;
              fixedMap->map->erase(n);
            }
          else
            it++;
        }
#endif

      topFixed = false;
    }
Example #7
0
// helper function for printing C code (copied from PL_Print1())
void C_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
{

  unsigned int upper, lower, num_bytes;
  Kind LHSkind, RHSkind;

  // os << spaces(indentation);
  // os << endl << spaces(indentation);
  if (!n.IsDefined())
  {
    os << "<undefined>";
    return;
  }

  // if this node is present in the letvar Map, then print the letvar
  STPMgr* bm = n.GetSTPMgr();

  // this is to print letvars for shared subterms inside the printing
  // of "(LET v0 = term1, v1=term1@term2,...
  if ((bm->NodeLetVarMap1.find(n) != bm->NodeLetVarMap1.end()) && !letize)
  {
    C_Print1(os, (bm->NodeLetVarMap1[n]), indentation, letize);
    return;
  }

  // this is to print letvars for shared subterms inside the actual
  // term to be printed
  if ((bm->NodeLetVarMap.find(n) != bm->NodeLetVarMap.end()) && letize)
  {
    C_Print1(os, (bm->NodeLetVarMap[n]), indentation, letize);
    return;
  }

  // otherwise print it normally
  Kind kind = n.GetKind();
  const ASTVec& c = n.GetChildren();
  switch (kind)
  {
    case BOOLEXTRACT:
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      C_Print1(os, c[0], indentation, letize);
      os << "{";
      C_Print1(os, c[1], indentation, letize);
      os << "}";
      break;
    case BITVECTOR:
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "BITVECTOR(";
      unsigned char* str;
      str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
      os << str << ")";
      CONSTANTBV::BitVector_Dispose(str);
      break;
    case BOOLEAN:
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "BOOLEAN";
      break;
    case FALSE:
      os << "0";
      break;
    case TRUE:
      os << "1";
      break;
    case BVCONST:
    case SYMBOL:
      // print in C friendly format:
      n.nodeprint(os, true);
      break;
    case READ:
      C_Print1(os, c[0], indentation, letize);
      os << "[";
      C_Print1(os, c[1], indentation, letize);
      os << "]";
      break;
    case WRITE:
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " WITH [";
      C_Print1(os, c[1], indentation, letize);
      os << "] := ";
      C_Print1(os, c[2], indentation, letize);
      os << ")";
      os << endl;
      break;
    case BVUMINUS:
      os << kind << "( ";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      break;
    case NOT:
      os << "!(";
      C_Print1(os, c[0], indentation, letize);
      os << ") " << endl;
      break;
    case BVNEG:
      os << " ~(";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      break;
    case BVCONCAT:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " @ ";
      C_Print1(os, c[1], indentation, letize);
      os << ")" << endl;
      break;
    case BVOR:
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " | ";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVAND:
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " & ";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVEXTRACT:

      // we only accept indices that are byte-aligned
      // (e.g., [15:8], [23:16])
      // and round down to byte indices rather than bit indices
      upper = c[1].GetUnsignedConst();
      lower = c[2].GetUnsignedConst();
      assert(upper > lower);
      assert(lower % 8 == 0);
      assert((upper + 1) % 8 == 0);
      num_bytes = (upper - lower + 1) / 8;
      assert(num_bytes > 0);

      // for multi-byte extraction, use the ADDRESS
      if (num_bytes > 1)
      {
        os << "&";
        C_Print1(os, c[0], indentation, letize);
        os << "[" << lower / 8 << "]";
      }
      // for single-byte extraction, use the VALUE
      else
      {
        C_Print1(os, c[0], indentation, letize);
        os << "[" << lower / 8 << "]";
      }

      break;
    case BVLEFTSHIFT:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " << ";
      os << c[1].GetUnsignedConst();
      os << ")";
      break;
    case BVRIGHTSHIFT:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << " >> ";
      os << c[1].GetUnsignedConst();
      os << ")";
      break;
    case BVMULT:
    case BVSUB:
    case BVPLUS:
    case SBVDIV:
    case SBVREM:
    case BVDIV:
    case BVMOD:
      os << kind << "(";
      os << n.GetValueWidth();
      for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
           it++)
      {
        os << ", " << endl;
        C_Print1(os, *it, indentation, letize);
      }
      os << ")" << endl;
      break;
    case ITE:
      os << "if (";
      C_Print1(os, c[0], indentation, letize);
      os << ")" << endl;
      os << "{";
      C_Print1(os, c[1], indentation, letize);
      os << endl << "} else {";
      C_Print1(os, c[2], indentation, letize);
      os << endl << "}";
      break;
    case BVLT:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " < ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVLE:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " <= ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVGT:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " > ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVGE:
      // convert to UNSIGNED before doing comparison!
      os << "((unsigned char)";
      C_Print1(os, c[0], indentation, letize);
      os << " >= ";
      os << "(unsigned char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVXOR:
    case BVNAND:
    case BVNOR:
    case BVXNOR:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      break;
    case BVSLT:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " < ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVSLE:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " <= ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVSGT:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " > ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case BVSGE:
      // convert to SIGNED before doing comparison!
      os << "((signed char)";
      C_Print1(os, c[0], indentation, letize);
      os << " >= ";
      os << "(signed char)";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      break;
    case EQ:
      // tricky tricky ... if it's a single-byte comparison,
      // simply do ==, but if it's multi-byte, must do memcmp
      LHSkind = c[0].GetKind();
      RHSkind = c[1].GetKind();

      num_bytes = 0;

      // try to figure out whether it's a single-byte or multi-byte
      // comparison
      if (LHSkind == BVEXTRACT)
      {
        upper = c[0].GetChildren()[1].GetUnsignedConst();
        lower = c[0].GetChildren()[2].GetUnsignedConst();
        num_bytes = (upper - lower + 1) / 8;
      }
      else if (RHSkind == BVEXTRACT)
      {
        upper = c[1].GetChildren()[1].GetUnsignedConst();
        lower = c[1].GetChildren()[2].GetUnsignedConst();
        num_bytes = (upper - lower + 1) / 8;
      }

      if (num_bytes > 1)
      {
        os << "(memcmp(";
        C_Print1(os, c[0], indentation, letize);
        os << ", ";
        C_Print1(os, c[1], indentation, letize);
        os << ", ";
        os << num_bytes;
        os << ") == 0)";
      }
      else if (num_bytes == 1)
      {
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " == ";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
      }
      else
      {
        FatalError("C_Print1: ugh problem in implementing ==");
      }

      break;
    case AND:
    case OR:
    case NAND:
    case NOR:
    case XOR:
    {
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      ASTVec::const_iterator it = c.begin();
      ASTVec::const_iterator itend = c.end();

      it++;
      for (; it != itend; it++)
      {
        switch (kind)
        {
          case AND:
            os << " && ";
            break;
          case OR:
            os << " || ";
            break;
          case NAND:
            FatalError("unsupported boolean type in C_Print1");
            break;
          case NOR:
            FatalError("unsupported boolean type in C_Print1");
            break;
          case XOR:
            FatalError("unsupported boolean type in C_Print1");
            break;
          default:
            FatalError("unsupported boolean type in C_Print1");
        }
        C_Print1(os, *it, indentation, letize);
      }
      os << ")";
      break;
    }
    case IFF:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      os << " <=> ";
      os << "(";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      os << ")";
      os << endl;
      break;
    case IMPLIES:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      os << "(";
      os << "(";
      C_Print1(os, c[0], indentation, letize);
      os << ")";
      os << " => ";
      os << "(";
      C_Print1(os, c[1], indentation, letize);
      os << ")";
      os << ")";
      os << endl;
      break;
    case BVSX:
      // stopgap for un-implemented features
      FatalError("C_Print1: printing not implemented for this kind: ", n);

      os << kind << "(";
      C_Print1(os, c[0], indentation, letize);
      os << ",";
      os << n.GetValueWidth();
      os << ")" << endl;
      break;
    default:
      // remember to use LispPrinter here. Otherwise this function will
      // go into an infinite loop. Recall that "<<" is overloaded to
      // the lisp printer. FatalError uses lispprinter
      FatalError("C_Print1: printing not implemented for this kind: ", n);
      break;
  }
} // end of C_Print1()
    Result
    dispatchToTransferFunctions(const Kind k, vector<FixedBits*>& children,
        FixedBits& output, const ASTNode n, MultiplicationStatsMap * msm)
    {
      Result result = NO_CHANGE;

      assert(!n.isConstant());

      Result(*transfer)(vector<FixedBits*>&, FixedBits&);

      switch (k)
        {
          case READ:
          case WRITE:
          // do nothing. Seems difficult to track properly.
          return NO_CHANGE;
          break;

#define MAPTFN(caseV, FN) case caseV: transfer = FN; break;

          // Shifting
          MAPTFN(BVLEFTSHIFT, bvLeftShiftBothWays)
          MAPTFN(BVRIGHTSHIFT, bvRightShiftBothWays)
          MAPTFN(BVSRSHIFT, bvArithmeticRightShiftBothWays)

          // Unsigned Comparison.
          MAPTFN(BVLT,bvLessThanBothWays)
          MAPTFN(BVLE,bvLessThanEqualsBothWays)
          MAPTFN(BVGT, bvGreaterThanBothWays)
          MAPTFN(BVGE, bvGreaterThanEqualsBothWays)

          // Signed Comparison.
          MAPTFN(BVSLT, bvSignedLessThanBothWays)
          MAPTFN(BVSGT,bvSignedGreaterThanBothWays)
          MAPTFN(BVSLE, bvSignedLessThanEqualsBothWays)
          MAPTFN(BVSGE, bvSignedGreaterThanEqualsBothWays)

          // Logic.
          MAPTFN(XOR,bvXorBothWays)
          MAPTFN(BVXOR, bvXorBothWays)
          MAPTFN(OR, bvOrBothWays)
          MAPTFN(BVOR, bvOrBothWays)
          MAPTFN(AND,bvAndBothWays)
          MAPTFN(BVAND,bvAndBothWays)
          MAPTFN(IFF, bvEqualsBothWays)
          MAPTFN(EQ, bvEqualsBothWays)
          MAPTFN(IMPLIES,bvImpliesBothWays)
          MAPTFN(NOT,bvNotBothWays)
          MAPTFN(BVNEG, bvNotBothWays)

          // OTHER
          MAPTFN(BVZX, bvZeroExtendBothWays)
          MAPTFN(BVSX, bvSignExtendBothWays)
          MAPTFN(BVUMINUS,bvUnaryMinusBothWays)
          MAPTFN(BVEXTRACT,bvExtractBothWays)
          MAPTFN(BVPLUS, bvAddBothWays)
          MAPTFN(BVSUB, bvSubtractBothWays)
          MAPTFN(ITE,bvITEBothWays)
          MAPTFN(BVCONCAT, bvConcatBothWays)

#ifdef WITHCBITP
          case BVMULT: // handled specially later.
          case BVDIV:
          case BVMOD:
          case SBVDIV:
          case SBVREM:
          case SBVMOD:
          transfer = NULL;
          break;
#endif
          default:
            {
              notHandled(k);
              return NO_CHANGE;
            }
        }
#undef MAPTFN
      bool mult_like = false;

#ifdef WITHCBITP
      // safe approximation to no overflow multiplication.
      if (k == BVMULT)
        {
          MultiplicationStats ms;
          result = bvMultiplyBothWays(children, output, n.GetSTPMgr(),&ms);
          		if (CONFLICT != result)
          			msm->map[n] = ms;
          mult_like=true;
        }
      else if (k == BVDIV)
        {
          result = bvUnsignedDivisionBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == BVMOD)
        {
          result = bvUnsignedModulusBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == SBVDIV)
        {
          result = bvSignedDivisionBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == SBVREM)
        {
          result = bvSignedRemainderBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else if (k == SBVMOD)
        {
          result = bvSignedModulusBothWays(children, output, n.GetSTPMgr());
          mult_like=true;
        }
      else
#endif
      result = transfer(children, output);

      if (mult_like && output_mult_like)
        {
          cerr << output << "=";
          cerr << *children[0] << k;
          cerr << *children[1] << std::endl;
        }

      return result;

    }
    // NB: This expects that the constructor was called with teh same node. Sorry.
    ASTNode
    ConstantBitPropagation::topLevelBothWays(const ASTNode& top)
    {
      assert(top.GetSTPMgr()->UserFlags.bitConstantProp_flag);
      assert (BOOLEAN_TYPE == top.GetType());

      propagate();
      status = NO_CHANGE;

      //Determine what must always be true.
      ASTNodeMap fromTo = getAllFixed();

      if (debug_cBitProp_messages)
        {
          cerr << "Number removed by bottom UP:" << fromTo.size() << endl;
        }

      setNodeToTrue(top);

      if (debug_cBitProp_messages)
        {
          cerr << "starting propagation" << endl;
          printNodeWithFixings();
          cerr << "Initial Tree:" << endl;
          cerr << top;
        }

      propagate();

      if (debug_cBitProp_messages)
        {
          cerr << "status:" << status <<endl;
          cerr << "ended propagation" << endl;
          printNodeWithFixings();
        }

      // propagate may have stopped with a conflict.
      if (CONFLICT == status)
          return top.GetSTPMgr()->CreateNode(FALSE);

      ASTVec toConjoin;

      // go through the fixedBits. If a node is entirely fixed.
      // "and" it onto the top. Creates redundancy. Check that the
      // node doesn't already depend on "top" directly.

      for (NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it = fixedMap->map->begin(); it != fixedMap->map->end(); it++) // iterates through all the pairs of node->fixedBits.
        {
          const FixedBits& bits = *it->second;

          if (!bits.isTotallyFixed())
            continue;

          const ASTNode& node = (it->first);

          // Don't constrain nodes we already know all about.
          if (node.isConstant())
            continue;

          // other nodes will contain the same information (the extract doesn't change the fixings).
          if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind())
            continue;

          // toAssign: conjoin it with the top level.
          // toReplace: replace all references to it (except the one conjoined to the top) with this.
          ASTNode propositionToAssert;
          ASTNode constantToReplaceWith;
          // skip the assigning and replacing.
          bool doAssign = true;

            {
              // If it is already contained in the fromTo map, then it's one of the values
              // that have fully been determined (previously). Not conjoined.
              if (fromTo.find(node) != fromTo.end())
                continue;

              ASTNode constNode = bitsToNode(node,bits);

              if (node.GetType() == BOOLEAN_TYPE)
                {
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else if (bits.getValue(0))
                    {
                      propositionToAssert = node;
                      constantToReplaceWith = constNode;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(NOT, node);
                      constantToReplaceWith = constNode;
                    }
                }
              else if (node.GetType() == BITVECTOR_TYPE)
                {
                  assert(((unsigned)bits.getWidth()) == node.GetValueWidth());
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(EQ, node, constNode);
                      constantToReplaceWith = constNode;
                    }
                }
              else
                FatalError("sadf234s");
            }

          if (doAssign && top != propositionToAssert
              && !dependents->nodeDependsOn(top, propositionToAssert))
            {
              assert(!constantToReplaceWith.IsNull());
              assert(constantToReplaceWith.isConstant());
              assert(propositionToAssert.GetType() == BOOLEAN_TYPE);
              assert(node.GetValueWidth() == constantToReplaceWith.GetValueWidth());

              fromTo.insert(make_pair(node, constantToReplaceWith));
              toConjoin.push_back(propositionToAssert);
            }
        }

     // Write the constants into the main graph.
      ASTNodeMap cache;
      ASTNode result = SubstitutionMap::replace(top, fromTo, cache,nf);

      if (0 != toConjoin.size())
        {
          // It doesn't happen very often. But the "toConjoin" might contain a variable
          // that was added to the substitution map (because the value was determined just now
          // during propagation.
          ASTNode conjunct = (1 == toConjoin.size())? toConjoin[0]: nf->CreateNode(AND,toConjoin);
          conjunct = simplifier->applySubstitutionMap(conjunct);

          result = nf->CreateNode(AND, result, conjunct); // conjoin the new conditions.
        }


  	if (debug_print_graph_after)
		{
			ofstream file;
			file.open("afterCbitp.gdl");
			PrintingHackfixedMap = fixedMap;
			printer::GDL_Print(file,top,&toString);
			file.close();
		}


      assert(BVTypeCheck(result));
      assert(status != CONFLICT); // conflict should have been seen earlier.
      return result;
    }