// 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()
void SMTLIB2_Print1(ostream& os, const ASTNode n, int indentation, bool letize) { //os << spaces(indentation); //os << endl << spaces(indentation); if (!n.IsDefined()) { FatalError("<undefined>"); return; } //if this node is present in the letvar Map, then print the letvar //this is to print letvars for shared subterms inside the printing //of "(LET v0 = term1, v1=term1@term2,... if ((NodeLetVarMap1.find(n) != NodeLetVarMap1.end()) && !letize) { SMTLIB2_Print1(os, (NodeLetVarMap1[n]), indentation, letize); return; } //this is to print letvars for shared subterms inside the actual //term to be printed if ((NodeLetVarMap.find(n) != NodeLetVarMap.end()) && letize) { SMTLIB2_Print1(os, (NodeLetVarMap[n]), indentation, letize); return; } //otherwise print it normally const Kind kind = n.GetKind(); const ASTVec &c = n.GetChildren(); switch (kind) { case BITVECTOR: case BVCONST: outputBitVecSMTLIB2(n, os); break; case SYMBOL: os << "|"; n.nodeprint(os); os << "|"; break; case FALSE: os << "false"; break; case NAND: // No NAND, NOR in smtlib format. case NOR: assert(c.size() ==2); os << "(" << "not "; if (NAND == kind ) os << "(" << "and "; else os << "(" << "or "; SMTLIB2_Print1(os, c[0], 0, letize); os << " " ; SMTLIB2_Print1(os, c[1], 0, letize); os << "))"; break; case TRUE: os << "true"; break; case BVSX: case BVZX: { unsigned int amount = c[1].GetUnsignedConst(); if (BVZX == kind) os << "((_ zero_extend "; else os << "((_ sign_extend "; os << (amount - c[0].GetValueWidth()) << ") "; SMTLIB2_Print1(os, c[0], indentation, letize); os << ")"; } break; case BVEXTRACT: { unsigned int upper = c[1].GetUnsignedConst(); unsigned int lower = c[2].GetUnsignedConst(); assert(upper >= lower); os << "((_ extract " << upper << " " << lower << ") "; SMTLIB2_Print1(os, c[0], indentation, letize); os << ")"; } break; default: { if ((kind == AND || kind == OR|| kind == XOR) && n.Degree() == 1) { FatalError("Wrong number of arguments to operation (must be >1).", n); } // SMT-LIB only allows these functions to have two parameters. if ((kind == AND || kind == OR|| kind == XOR || BVPLUS == kind || kind == BVOR || kind == BVAND) && n.Degree() > 2) { string close = ""; for (long int i =0; i < (long int)c.size()-1; i++) { os << "(" << functionToSMTLIBName(kind,false); os << " "; SMTLIB2_Print1(os, c[i], 0, letize); os << " "; close += ")"; } SMTLIB2_Print1(os, c[c.size()-1], 0, letize); os << close; } else { os << "(" << functionToSMTLIBName(kind,false); ASTVec::const_iterator iend = c.end(); for (ASTVec::const_iterator i = c.begin(); i != iend; i++) { os << " "; SMTLIB2_Print1(os, *i, 0, letize); } os << ")"; } } } }