BtorTranslationPolicy::BtorTranslationPolicy(BtorTranslationHooks* hooks, uint32_t minNumStepsToFindError, uint32_t maxNumStepsToFindError, SgProject* proj): problem(), hooks(hooks), regdict(NULL) {
  assert (minNumStepsToFindError >= 1); // Can't find an error on the first step
  assert (maxNumStepsToFindError < 0xFFFFFFFFU); // Prevent overflows
  assert (minNumStepsToFindError <= maxNumStepsToFindError || maxNumStepsToFindError == 0);
  makeRegMap(origRegisterMap, "");
  makeRegMapZero(newRegisterMap);
  isValidIp = false_();
  validIPs.clear();
  Comp stepCount = problem.build_var(32, "stepCount_saturating_at_" + boost::lexical_cast<std::string>(maxNumStepsToFindError + 1));
  addNext(stepCount, ite(problem.build_op_eq(stepCount, number<32>(maxNumStepsToFindError + 1)), number<32>(maxNumStepsToFindError + 1), problem.build_op_inc(stepCount)));
  resetState = problem.build_op_eq(stepCount, zero(32));
  errorsEnabled =
    problem.build_op_and(
      problem.build_op_ugte(stepCount, number<32>(minNumStepsToFindError)),
      (maxNumStepsToFindError == 0 ?
       true_() :
       problem.build_op_ulte(stepCount, number<32>(maxNumStepsToFindError))));
  {
    vector<SgNode*> functions = NodeQuery::querySubTree(proj, V_SgAsmFunction);
    for (size_t i = 0; i < functions.size(); ++i) {
      functionStarts.push_back(isSgAsmFunction(functions[i])->get_address());
      // fprintf(stderr, "functionStarts 0x%"PRIx64"\n", isSgAsmFunction(functions[i])->get_address());
    }
  }
  {
    vector<SgNode*> blocks = NodeQuery::querySubTree(proj, V_SgAsmBlock);
    for (size_t i = 0; i < blocks.size(); ++i) {
      SgAsmBlock* b = isSgAsmBlock(blocks[i]);
      if (!b->get_statementList().empty() && isSgAsmX86Instruction(b->get_statementList().front())) {
        blockStarts.push_back(b->get_address());
        // fprintf(stderr, "blockStarts 0x%"PRIx64"\n", b->get_address());
      }
    }
  }
  {
    vector<SgNode*> calls = NodeQuery::querySubTree(proj, V_SgAsmX86Instruction);
    for (size_t i = 0; i < calls.size(); ++i) {
      SgAsmX86Instruction* b = isSgAsmX86Instruction(calls[i]);
      if (b->get_kind() != x86_call) continue;
      returnPoints.push_back(b->get_address() + b->get_raw_bytes().size());
      // fprintf(stderr, "returnPoints 0x%"PRIx64"\n", b->get_address() + b->get_raw_bytes().size());
    }
  }
  {
    vector<SgNode*> instructions = NodeQuery::querySubTree(proj, V_SgAsmX86Instruction);
    for (size_t i = 0; i < instructions.size(); ++i) {
      SgAsmX86Instruction* b = isSgAsmX86Instruction(instructions[i]);
      validIPs.push_back(b->get_address());
    }
  }
}
 virtual void visit(SgNode* n) {
     SgAsmX86Instruction* insn = isSgAsmX86Instruction(n);
     if (!insn) return;
     if (insn->get_kind() != x86_call) return;
     //cerr << "Found call xxx at " << hex << insn->get_address() << endl;
     uint64_t tgtAddr;
     if (!insn->getBranchTarget(&tgtAddr)) return;
     //cerr << "Found call at " << hex << insn->get_address() << " with known target " << hex << tgtAddr << endl;
     SgAsmInstruction* tgt = info->getInstructionAtAddress(tgtAddr);
     if (!tgt) return;
     //cerr << "Found target insn" << endl;
     SgNode* f = tgt;
     while (f && !isSgAsmBlock(f) && !isSgAsmFunction(f)) f = f->get_parent();
     if (!f) return;
     //cerr << "Found function of target" << endl;
     uint64_t next = insn->get_address() + insn->get_raw_bytes().size();
     info->returnTargets[isSgAsmStatement(f)].insert(next);
 }