// -*- c++ -*-
#include "AST.h"
+
+#include <assert.h>
+
namespace BEEV {
//some global variables that are set through commandline options. it
//is best that these variables remain global. Default values set
}
} //end of PL_Print1()
+
+ // printer for C code (copied from PL_Print())
+ // TODO: this does not fully implement printing of all of the STP
+ // language - FatalError calls inserted for unimplemented
+ // functionality, e.g.,:
+ // FatalError("C_Print1: printing not implemented for this kind: ",*this);
+
+ //two pass algorithm:
+ //
+ //1. In the first pass, letize this Node, N: i.e. if a node
+ //1. appears more than once in N, then record this fact.
+ //
+ //2. In the second pass print a "global let" and then print N
+ //2. as follows: Every occurence of a node occuring more than
+ //2. once is replaced with the corresponding let variable.
+ ostream& ASTNode::C_Print(ostream &os,
+ int indentation) const {
+ // Clear the PrintMap
+ BeevMgr& bm = GetBeevMgr();
+ bm.PLPrintNodeSet.clear();
+ bm.NodeLetVarMap.clear();
+ bm.NodeLetVarVec.clear();
+ bm.NodeLetVarMap1.clear();
+
+ //pass 1: letize the node
+ LetizeNode();
+
+ unsigned int lower, upper, num_bytes = 0;
+
+ //pass 2:
+ //
+ //2. print all the let variables and their counterpart expressions
+ //2. as follows (LET var1 = expr1, var2 = expr2, ...
+ //
+ //3. Then print the Node itself, replacing every occurence of
+ //3. expr1 with var1, expr2 with var2, ...
+ //os << "(";
+ if(0 < bm.NodeLetVarMap.size()) {
+ //ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
+ //ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
+ std::vector<pair<ASTNode,ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
+ std::vector<pair<ASTNode,ASTNode> >::iterator itend = bm.NodeLetVarVec.end();
+
+ // start a new block to create new static scope
+ os << "{" << endl;
+
+ for(;it!=itend;it++) {
+
+ // see if it's a BVEXTRACT, and if so, whether it's multi-byte
+ if (it->second.GetKind() == BVEXTRACT) {
+ upper = GetUnsignedConst(it->second.GetChildren()[1]);
+ lower = GetUnsignedConst(it->second.GetChildren()[2]);
+ num_bytes = (upper - lower + 1) / 8;
+ assert(num_bytes > 0);
+ }
+
+ //print the let var first
+ if (num_bytes > 1) {
+ // for multi-byte assignment, use 'memcpy' and array notation
+ os << "unsigned char ";
+ it->first.C_Print1(os,indentation,false);
+ os << "[" << num_bytes << "]; ";
+ os << "memcpy(";
+ it->first.C_Print1(os,indentation,false);
+ os << ", ";
+ //print the expr
+ it->second.C_Print1(os,indentation,false);
+ os << ", " << num_bytes << ");";
+ }
+ else {
+ // for single-byte assignment, use '='
+ os << "unsigned char ";
+ it->first.C_Print1(os,indentation,false);
+ os << " = ";
+ //print the expr
+ it->second.C_Print1(os,indentation,false);
+ os << ";" << endl;
+ }
+
+ //update the second map for proper printing of LET
+ bm.NodeLetVarMap1[it->second] = it->first;
+ }
+
+ os << endl << "stp_assert ";
+ C_Print1(os,indentation, true);
+
+ os << ";" << endl << "}";
+ }
+ else {
+ os << "stp_assert ";
+ C_Print1(os,indentation, false);
+ os << ";";
+ }
+ //os << " )";
+ //os << " ";
+
+ return os;
+ } //end of C_Print()
+
+ // helper function for printing C code (copied from PL_Print1())
+ void ASTNode::C_Print1(ostream& os,
+ int indentation,
+ bool letize) const {
+
+ unsigned int upper, lower, num_bytes;
+ Kind LHSkind, RHSkind;
+
+ //os << spaces(indentation);
+ //os << endl << spaces(indentation);
+ if (!IsDefined()) {
+ os << "<undefined>";
+ return;
+ }
+
+ //if this node is present in the letvar Map, then print the letvar
+ BeevMgr &bm = GetBeevMgr();
+
+ //this is to print letvars for shared subterms inside the printing
+ //of "(LET v0 = term1, v1=term1@term2,...
+ if((bm.NodeLetVarMap1.find(*this) != bm.NodeLetVarMap1.end()) && !letize) {
+ (bm.NodeLetVarMap1[*this]).C_Print1(os,indentation,letize);
+ return;
+ }
+
+ //this is to print letvars for shared subterms inside the actual
+ //term to be printed
+ if((bm.NodeLetVarMap.find(*this) != bm.NodeLetVarMap.end()) && letize) {
+ (bm.NodeLetVarMap[*this]).C_Print1(os,indentation,letize);
+ return;
+ }
+
+ //otherwise print it normally
+ Kind kind = GetKind();
+ const ASTVec &c = GetChildren();
+ switch(kind) {
+ case BVGETBIT:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this);
+ c[0].C_Print1(os,indentation,letize);
+ os << "{";
+ c[1].C_Print1(os,indentation,letize);
+ os << "}";
+ break;
+ case BITVECTOR:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this);
+ 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: ",*this);
+ os << "BOOLEAN";
+ break;
+ case FALSE:
+ os << "0";
+ break;
+ case TRUE:
+ os << "1";
+ break;
+ case BVCONST:
+ case SYMBOL:
+ // print in C friendly format:
+ _int_node_ptr->nodeprint(os, true);
+ break;
+ case READ:
+ c[0].C_Print1(os, indentation,letize);
+ os << "[";
+ c[1].C_Print1(os,indentation,letize);
+ os << "]";
+ break;
+ case WRITE:
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " WITH [";
+ c[1].C_Print1(os,indentation,letize);
+ os << "] := ";
+ c[2].C_Print1(os,indentation,letize);
+ os << ")";
+ os << endl;
+ break;
+ case BVUMINUS:
+ os << kind << "( ";
+ c[0].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case NOT:
+ os << "!(";
+ c[0].C_Print1(os,indentation,letize);
+ os << ") " << endl;
+ break;
+ case BVNEG:
+ os << " ~(";
+ c[0].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVCONCAT:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " @ ";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")" << endl;
+ break;
+ case BVOR:
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " | ";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVAND:
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " & ";
+ c[1].C_Print1(os,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 = GetUnsignedConst(c[1]);
+ lower = GetUnsignedConst(c[2]);
+ 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[0].C_Print1(os,indentation,letize);
+ os << "[" << lower / 8 << "]";
+ }
+ // for single-byte extraction, use the VALUE
+ else {
+ c[0].C_Print1(os,indentation,letize);
+ os << "[" << lower / 8 << "]";
+ }
+
+ break;
+ case BVLEFTSHIFT:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " << ";
+ os << GetUnsignedConst(c[1]);
+ os << ")";
+ break;
+ case BVRIGHTSHIFT:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " >> ";
+ os << GetUnsignedConst(c[1]);
+ os << ")";
+ break;
+ case BVMULT:
+ case BVSUB:
+ case BVPLUS:
+ case SBVDIV:
+ case SBVREM:
+ case BVDIV:
+ case BVMOD:
+ os << kind << "(";
+ os << this->GetValueWidth();
+ for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ os << ", " << endl;
+ it->C_Print1(os,indentation,letize);
+ }
+ os << ")" << endl;
+ break;
+ case ITE:
+ os << "if (";
+ c[0].C_Print1(os,indentation,letize);
+ os << ")" << endl;
+ os << "{";
+ c[1].C_Print1(os,indentation,letize);
+ os << endl << "} else {";
+ c[2].C_Print1(os,indentation,letize);
+ os << endl << "}";
+ break;
+ case BVLT:
+ // convert to UNSIGNED before doing comparison!
+ os << "((unsigned char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " < ";
+ os << "(unsigned char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVLE:
+ // convert to UNSIGNED before doing comparison!
+ os << "((unsigned char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " <= ";
+ os << "(unsigned char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVGT:
+ // convert to UNSIGNED before doing comparison!
+ os << "((unsigned char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " > ";
+ os << "(unsigned char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVGE:
+ // convert to UNSIGNED before doing comparison!
+ os << "((unsigned char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " >= ";
+ os << "(unsigned char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVXOR:
+ case BVNAND:
+ case BVNOR:
+ case BVXNOR:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+ break;
+ case BVSLT:
+ // convert to SIGNED before doing comparison!
+ os << "((signed char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " < ";
+ os << "(signed char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVSLE:
+ // convert to SIGNED before doing comparison!
+ os << "((signed char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " <= ";
+ os << "(signed char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVSGT:
+ // convert to SIGNED before doing comparison!
+ os << "((signed char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " > ";
+ os << "(signed char)";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ break;
+ case BVSGE:
+ // convert to SIGNED before doing comparison!
+ os << "((signed char)";
+ c[0].C_Print1(os,indentation,letize);
+ os << " >= ";
+ os << "(signed char)";
+ c[1].C_Print1(os,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 = GetUnsignedConst(c[0].GetChildren()[1]);
+ lower = GetUnsignedConst(c[0].GetChildren()[2]);
+ num_bytes = (upper - lower + 1) / 8;
+ }
+ else if (RHSkind == BVEXTRACT) {
+ upper = GetUnsignedConst(c[1].GetChildren()[1]);
+ lower = GetUnsignedConst(c[1].GetChildren()[2]);
+ num_bytes = (upper - lower + 1) / 8;
+ }
+
+ if (num_bytes > 1) {
+ os << "(memcmp(";
+ c[0].C_Print1(os,indentation,letize);
+ os << ", ";
+ c[1].C_Print1(os,indentation,letize);
+ os << ", ";
+ os << num_bytes;
+ os << ") == 0)";
+ }
+ else if (num_bytes == 1) {
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << " == ";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ }
+ else {
+ FatalError("C_Print1: ugh problem in implementing ==");
+ }
+
+ break;
+ case NEQ:
+ c[0].C_Print1(os,indentation,letize);
+ os << " != ";
+ c[1].C_Print1(os,indentation,letize);
+ os << endl;
+ break;
+ case AND:
+ case OR:
+ case NAND:
+ case NOR:
+ case XOR: {
+ os << "(";
+ c[0].C_Print1(os,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");
+ }
+ it->C_Print1(os,indentation,letize);
+ }
+ os << ")";
+ break;
+ }
+ case IFF:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+ os << "(";
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << ")";
+ os << " <=> ";
+ os << "(";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ os << ")";
+ os << endl;
+ break;
+ case IMPLIES:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+ os << "(";
+ os << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << ")";
+ os << " => ";
+ os << "(";
+ c[1].C_Print1(os,indentation,letize);
+ os << ")";
+ os << ")";
+ os << endl;
+ break;
+ case BVSX:
+ FatalError("C_Print1: printing not implemented for this kind: ",*this); // stopgap for un-implemented features
+
+ os << kind << "(";
+ c[0].C_Print1(os,indentation,letize);
+ os << ",";
+ os << this->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: ",*this);
+ break;
+ }
+ } //end of C_Print1()
+
+
////////////////////////////////////////////////////////////////
// BeevMgr members
////////////////////////////////////////////////////////////////