[llvm-commits] [klee] r72205 [3/3] - in /klee/trunk: ./ autoconf/ docs/ docs/SMT-COMP/ examples/ examples/regexp/ examples/sort/ include/ include/expr/ include/klee/ include/klee/Config/ include/klee/Internal/ include/klee/Internal/ADT/ include/klee/Internal/Module/ include/klee/Internal/Support/ include/klee/Internal/System/ include/klee/util/ lib/ lib/Basic/ lib/Core/ lib/Expr/ lib/Module/ lib/Solver/ lib/Support/ runtime/ runtime/Intrinsic/ runtime/POSIX/ runtime/POSIX/testing-dir/ runtime/POSIX/testing-dir/e/ runti...
Daniel Dunbar
daniel at zuster.org
Wed May 20 21:36:47 PDT 2009
Added: klee/trunk/stp/parser/PL.y
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/PL.y?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/parser/PL.y (added)
+++ klee/trunk/stp/parser/PL.y Wed May 20 23:36:41 2009
@@ -0,0 +1,1006 @@
+%{
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+using namespace std;
+
+ // Suppress the bogus warning suppression in bison (it generates
+ // compile error)
+#undef __GNUC_MINOR__
+
+ extern int yylex(void);
+ extern char* yytext;
+ extern int yylineno;
+ int yyerror(const char *s) {
+ cout << "syntax error: line " << yylineno << "\n" << s << endl;
+ BEEV::FatalError("");
+ return 1; /* Dill: don't know what it should return */
+ };
+
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYMAXDEPTH 10485760
+#define YYERROR_VERBOSE 1
+#define YY_EXIT_FAILURE -1
+%}
+
+%union {
+
+ unsigned int uintval; /* for numerals in types. */
+ struct {
+ //stores the indexwidth and valuewidth
+ //indexwidth is 0 iff type is bitvector. positive iff type is
+ //array, and stores the width of the indexing bitvector
+ unsigned int indexwidth;
+ //width of the bitvector type
+ unsigned int valuewidth;
+ } indexvaluewidth;
+
+ //ASTNode,ASTVec
+ BEEV::ASTNode *node;
+ BEEV::ASTVec *vec;
+
+ //Hash_Map to hold Array Updates during parse A map from array index
+ //to array values. To support the WITH construct
+ BEEV::ASTNodeMap * Index_To_UpdateValue;
+};
+
+%start cmd
+
+%token AND_TOK "AND"
+%token OR_TOK "OR"
+%token NOT_TOK "NOT"
+%token XOR_TOK "XOR"
+%token NAND_TOK "NAND"
+%token NOR_TOK "NOR"
+%token IMPLIES_TOK "=>"
+%token IFF_TOK "<=>"
+
+%token IF_TOK "IF"
+%token THEN_TOK "THEN"
+%token ELSE_TOK "ELSE"
+%token ELSIF_TOK "ELSIF"
+%token END_TOK "END"
+%token ENDIF_TOK "ENDIF"
+%token NEQ_TOK "/="
+%token ASSIGN_TOK ":="
+
+%token BV_TOK "BV"
+%token BVLEFTSHIFT_TOK "<<"
+%token BVRIGHTSHIFT_TOK ">>"
+%token BVPLUS_TOK "BVPLUS"
+%token BVSUB_TOK "BVSUB"
+%token BVUMINUS_TOK "BVUMINUS"
+%token BVMULT_TOK "BVMULT"
+
+%token BVDIV_TOK "BVDIV"
+%token BVMOD_TOK "BVMOD"
+%token SBVDIV_TOK "SBVDIV"
+%token SBVMOD_TOK "SBVMOD"
+
+
+%token BVNEG_TOK "~"
+%token BVAND_TOK "&"
+%token BVOR_TOK "|"
+%token BVXOR_TOK "BVXOR"
+%token BVNAND_TOK "BVNAND"
+%token BVNOR_TOK "BVNOR"
+%token BVXNOR_TOK "BVXNOR"
+%token BVCONCAT_TOK "@"
+
+%token BVLT_TOK "BVLT"
+%token BVGT_TOK "BVGT"
+%token BVLE_TOK "BVLE"
+%token BVGE_TOK "BVGE"
+
+%token BVSLT_TOK "BVSLT"
+%token BVSGT_TOK "BVSGT"
+%token BVSLE_TOK "BVSLE"
+%token BVSGE_TOK "BVSGE"
+%token BOOL_TO_BV_TOK "BOOLBV"
+%token BVSX_TOK "BVSX"
+%token BOOLEXTRACT_TOK "BOOLEXTRACT"
+%token ASSERT_TOK "ASSERT"
+%token QUERY_TOK "QUERY"
+
+%token BOOLEAN_TOK "BOOLEAN"
+%token ARRAY_TOK "ARRAY"
+%token OF_TOK "OF"
+%token WITH_TOK "WITH"
+
+%token TRUELIT_TOK "TRUE"
+%token FALSELIT_TOK "FALSE"
+
+%token IN_TOK "IN"
+%token LET_TOK "LET"
+//%token COUNTEREXAMPLE_TOK "COUNTEREXAMPLE"
+%token PUSH_TOK "PUSH"
+%token POP_TOK "POP"
+
+%left IN_TOK
+%left XOR_TOK
+%left IFF_TOK
+%right IMPLIES_TOK
+%left OR_TOK
+%left AND_TOK
+%left NAND_TOK
+%left NOR_TOK
+%left NOT_TOK
+%left BVCONCAT_TOK
+%left BVOR_TOK
+%left BVAND_TOK
+%left BVXOR_TOK
+%left BVNAND_TOK
+%left BVNOR_TOK
+%left BVXNOR_TOK
+%left BVNEG_TOK
+%left BVLEFTSHIFT_TOK BVRIGHTSHIFT_TOK
+%left WITH_TOK
+
+%nonassoc '=' NEQ_TOK ASSIGN_TOK
+%nonassoc BVLT_TOK BVLE_TOK BVGT_TOK BVGE_TOK
+%nonassoc BVUMINUS_TOK BVPLUS_TOK BVSUB_TOK BVSX_TOK
+%nonassoc '['
+%nonassoc '{' '.' '('
+%nonassoc BV_TOK
+
+%type <vec> Exprs FORM_IDs reverseFORM_IDs
+%type <vec> Asserts
+%type <node> Expr Formula IfExpr ElseRestExpr IfForm ElseRestForm Assert Query ArrayUpdateExpr
+%type <Index_To_UpdateValue> Updates
+
+%type <indexvaluewidth> BvType BoolType ArrayType Type
+
+%token <node> BVCONST_TOK
+%token <node> TERMID_TOK FORMID_TOK COUNTEREXAMPLE_TOK
+%token <uintval> NUMERAL_TOK
+
+%%
+
+cmd : other_cmd
+ | other_cmd counterexample
+ ;
+
+counterexample : COUNTEREXAMPLE_TOK ';'
+ {
+ BEEV::print_counterexample = true;
+ BEEV::globalBeevMgr_for_parser->PrintCounterExample(true);
+ }
+ ;
+
+other_cmd : other_cmd1
+ | Query
+ {
+ BEEV::globalBeevMgr_for_parser->TopLevelSAT(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE),*$1);
+ delete $1;
+ }
+ | VarDecls Query
+ {
+ BEEV::globalBeevMgr_for_parser->TopLevelSAT(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE),*$2);
+ delete $2;
+ }
+ | other_cmd1 Query
+ {
+ BEEV::ASTVec aaa = BEEV::globalBeevMgr_for_parser->GetAsserts();
+ if(aaa.size() == 0)
+ yyerror("Fatal Error: parsing: GetAsserts() call: no assertions: ");
+ if(aaa.size() == 1)
+ BEEV::globalBeevMgr_for_parser->TopLevelSAT(aaa[0],*$2);
+ else
+ BEEV::globalBeevMgr_for_parser->TopLevelSAT(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND,aaa),*$2);
+ delete $2;
+ }
+ ;
+
+other_cmd1 : VarDecls Asserts
+ {
+ delete $2;
+ }
+ | Asserts
+ {
+ delete $1;
+ }
+ | other_cmd1 VarDecls Asserts
+ {
+ delete $3;
+ }
+ ;
+
+/* push : PUSH_TOK */
+/* { */
+/* BEEV::globalBeevMgr_for_parser->Push(); */
+/* } */
+/* | */
+/* ; */
+
+/* pop : POP_TOK */
+/* { */
+/* BEEV::globalBeevMgr_for_parser->Pop(); */
+/* } */
+/* | */
+/* ; */
+
+Asserts : Assert
+ {
+ $$ = new BEEV::ASTVec;
+ $$->push_back(*$1);
+ BEEV::globalBeevMgr_for_parser->AddAssert(*$1);
+ delete $1;
+ }
+ | Asserts Assert
+ {
+ $1->push_back(*$2);
+ BEEV::globalBeevMgr_for_parser->AddAssert(*$2);
+ $$ = $1;
+ delete $2;
+ }
+ ;
+
+Assert : ASSERT_TOK Formula ';' { $$ = $2; }
+ ;
+
+Query : QUERY_TOK Formula ';' { BEEV::globalBeevMgr_for_parser->AddQuery(*$2); $$ = $2;}
+ ;
+
+
+/* Grammar for Variable Declaration */
+VarDecls : VarDecl ';'
+ {
+ }
+ | VarDecls VarDecl ';'
+ {
+ }
+ ;
+
+VarDecl : FORM_IDs ':' Type
+ {
+ for(BEEV::ASTVec::iterator i=$1->begin(),iend=$1->end();i!=iend;i++) {
+ BEEV::_parser_symbol_table.insert(*i);
+ i->SetIndexWidth($3.indexwidth);
+ i->SetValueWidth($3.valuewidth);
+
+ //FIXME: HACK_ATTACK. this vector was hacked into the code to
+ //support a special request by Dawson' group. They want the
+ //counterexample to be printed in the order of variables declared.
+ BEEV::globalBeevMgr_for_parser->_special_print_set.push_back(*i);
+ }
+ delete $1;
+ }
+ | FORM_IDs ':' Type '=' Expr
+ {
+ //do type checking. if doesn't pass then abort
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+ if($3.indexwidth != $5->GetIndexWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+ if($3.valuewidth != $5->GetValueWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+
+ for(BEEV::ASTVec::iterator i=$1->begin(),iend=$1->end();i!=iend;i++) {
+ //set the valuewidth of the identifier
+ i->SetValueWidth($5->GetValueWidth());
+ i->SetIndexWidth($5->GetIndexWidth());
+
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*i,*$5);
+ delete $5;
+ }
+ }
+ | FORM_IDs ':' Type '=' Formula
+ {
+ //do type checking. if doesn't pass then abort
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+ if($3.indexwidth != $5->GetIndexWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+ if($3.valuewidth != $5->GetValueWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+
+ for(BEEV::ASTVec::iterator i=$1->begin(),iend=$1->end();i!=iend;i++) {
+ //set the valuewidth of the identifier
+ i->SetValueWidth($5->GetValueWidth());
+ i->SetIndexWidth($5->GetIndexWidth());
+
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*i,*$5);
+ delete $5;
+ }
+ }
+ ;
+
+reverseFORM_IDs : FORMID_TOK
+ {
+ $$ = new BEEV::ASTVec;
+ $$->push_back(*$1);
+ delete $1;
+ }
+ | FORMID_TOK ',' reverseFORM_IDs
+ {
+ $3->push_back(*$1);
+ $$ = $3;
+ delete $1;
+ }
+ ;
+
+FORM_IDs : reverseFORM_IDs
+ {
+ $$ = new BEEV::ASTVec($1->rbegin(),$1->rend());
+ delete $1;
+ }
+ ;
+
+/* Grammar for Types */
+Type : BvType { $$ = $1; }
+ | BoolType { $$ = $1; }
+ | ArrayType { $$ = $1; }
+ ;
+
+BvType : BV_TOK '(' NUMERAL_TOK ')'
+ {
+ /*((indexwidth is 0) && (valuewidth>0)) iff type is BV*/
+ $$.indexwidth = 0;
+ unsigned int length = $3;
+ if(length > 0) {
+ $$.valuewidth = length;
+ }
+ else
+ BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+ }
+ ;
+BoolType : BOOLEAN_TOK
+ {
+ $$.indexwidth = 0;
+ $$.valuewidth = 0;
+ }
+ ;
+ArrayType : ARRAY_TOK BvType OF_TOK BvType
+ {
+ $$.indexwidth = $2.valuewidth;
+ $$.valuewidth = $4.valuewidth;
+ }
+ ;
+
+/*Grammar for ITEs which are a type of Term*/
+IfExpr : IF_TOK Formula THEN_TOK Expr ElseRestExpr
+ {
+ unsigned int width = $4->GetValueWidth();
+ if (width != $5->GetValueWidth())
+ yyerror("Width mismatch in IF-THEN-ELSE");
+ if($4->GetIndexWidth() != $5->GetIndexWidth())
+ yyerror("Width mismatch in IF-THEN-ELSE");
+
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE, width, *$2, *$4, *$5));
+ $$->SetIndexWidth($5->GetIndexWidth());
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$);
+ delete $2;
+ delete $4;
+ delete $5;
+ }
+ ;
+
+ElseRestExpr : ELSE_TOK Expr ENDIF_TOK { $$ = $2; }
+ | ELSIF_TOK Expr THEN_TOK Expr ElseRestExpr
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $4->GetValueWidth() || width != $5->GetValueWidth())
+ yyerror("Width mismatch in IF-THEN-ELSE");
+ if ($2->GetIndexWidth() != $4->GetValueWidth() || $2->GetIndexWidth() != $5->GetValueWidth())
+ yyerror("Width mismatch in IF-THEN-ELSE");
+
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE, width, *$2, *$4, *$5));
+ $$->SetIndexWidth($5->GetIndexWidth());
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$);
+ delete $2;
+ delete $4;
+ delete $5;
+ }
+ ;
+
+/* Grammar for formulas */
+Formula : '(' Formula ')' { $$ = $2; }
+ | FORMID_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1;}
+ | BOOLEXTRACT_TOK '(' Expr ',' NUMERAL_TOK ')'
+ {
+ unsigned int width = $3->GetValueWidth();
+ if(0 > (unsigned)$5 || width <= (unsigned)$5)
+ yyerror("Fatal Error: BOOLEXTRACT: trying to boolextract a bit which beyond range");
+
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,1,*$3,hi,low));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ BEEV::ASTNode zero = BEEV::globalBeevMgr_for_parser->CreateBVConst(1,0);
+ BEEV::ASTNode * out = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::EQ,*n,zero));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*out);
+
+ $$ = out;
+ delete $3;
+ }
+ | Expr '=' Expr
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::EQ, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $1;
+ delete $3;
+ }
+ | Expr NEQ_TOK Expr
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NEQ, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $1;
+ delete $3;
+ }
+ | NOT_TOK Formula
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT, *$2));
+ delete $2;
+ }
+ | Formula OR_TOK Formula %prec OR_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::OR, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | Formula NOR_TOK Formula
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOR, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | Formula AND_TOK Formula %prec AND_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | Formula NAND_TOK Formula
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NAND, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | Formula IMPLIES_TOK Formula
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IMPLIES, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | Formula IFF_TOK Formula
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IFF, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | Formula XOR_TOK Formula
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::XOR, *$1, *$3));
+ delete $1;
+ delete $3;
+ }
+ | BVLT_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLT, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVGT_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGT, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVLE_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLE, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVGE_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGE, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVSLT_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLT, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVSGT_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGT, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVSLE_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLE, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVSGE_TOK '(' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGE, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | IfForm
+ | TRUELIT_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE));
+ $$->SetIndexWidth(0);
+ $$->SetValueWidth(0);
+ }
+ | FALSELIT_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::FALSE));
+ $$->SetIndexWidth(0);
+ $$->SetValueWidth(0);
+ }
+
+ | LET_TOK LetDecls IN_TOK Formula
+ {
+ $$ = $4;
+ //Cleanup the LetIDToExprMap
+ BEEV::globalBeevMgr_for_parser->CleanupLetIDMap();
+ }
+ ;
+
+/*Grammar for ITEs which are Formulas */
+IfForm : IF_TOK Formula THEN_TOK Formula ElseRestForm
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$2, *$4, *$5));
+ delete $2;
+ delete $4;
+ delete $5;
+ }
+ ;
+
+ElseRestForm : ELSE_TOK Formula ENDIF_TOK { $$ = $2; }
+ | ELSIF_TOK Formula THEN_TOK Formula ElseRestForm
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$2, *$4, *$5));
+ delete $2;
+ delete $4;
+ delete $5;
+ }
+ ;
+
+/*Grammar for a list of expressions*/
+Exprs : Expr
+ {
+ $$ = new BEEV::ASTVec;
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$1);
+ $$->push_back(*$1);
+ delete $1;
+ }
+ | Exprs ',' Expr
+ {
+ $1->push_back(*$3);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+ $$ = $1;
+ delete $3;
+ }
+ ;
+
+/* Grammar for Expr */
+Expr : TERMID_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1;}
+ | '(' Expr ')' { $$ = $2; }
+ | BVCONST_TOK { $$ = $1; }
+ | BOOL_TO_BV_TOK '(' Formula ')'
+ {
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+ BEEV::ASTNode one = BEEV::globalBeevMgr_for_parser->CreateBVConst(1,1);
+ BEEV::ASTNode zero = BEEV::globalBeevMgr_for_parser->CreateBVConst(1,0);
+
+ //return ITE(*$3, length(1), 0bin1, 0bin0)
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE,1,*$3,one,zero));
+ delete $3;
+ }
+ | Expr '[' Expr ']'
+ {
+ // valuewidth is same as array, indexwidth is 0.
+ unsigned int width = $1->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $1;
+ delete $3;
+ }
+ | Expr '(' Expr ')' //array read but in the form of a uninterpreted function application
+ {
+ // valuewidth is same as array, indexwidth is 0.
+ unsigned int width = $1->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $1;
+ delete $3;
+ }
+ | Expr '[' NUMERAL_TOK ':' NUMERAL_TOK ']'
+ {
+ int width = $3 - $5 + 1;
+ if (width < 0)
+ yyerror("Negative width in extract");
+
+ if((unsigned)$3 >= $1->GetValueWidth() || (unsigned)$5 < 0)
+ yyerror("Parsing: Wrong width in BVEXTRACT\n");
+
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $3);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT, width, *$1,hi,low));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $1;
+ }
+ | BVNEG_TOK Expr
+ {
+ unsigned int width = $2->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNEG, width, *$2));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ }
+ | Expr BVAND_TOK Expr
+ {
+ unsigned int width = $1->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in AND");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVAND, width, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $1;
+ delete $3;
+ }
+ | Expr BVOR_TOK Expr
+ {
+ unsigned int width = $1->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in OR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVOR, width, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $1;
+ delete $3;
+ }
+ | BVXOR_TOK '(' Expr ',' Expr ')'
+ {
+ unsigned int width = $3->GetValueWidth();
+ if (width != $5->GetValueWidth()) {
+ yyerror("Width mismatch in XOR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXOR, width, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $5;
+ }
+ | BVNAND_TOK '(' Expr ',' Expr ')'
+ {
+ unsigned int width = $3->GetValueWidth();
+ if (width != $5->GetValueWidth()) {
+ yyerror("Width mismatch in NAND");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNAND, width, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $3;
+ delete $5;
+ }
+ | BVNOR_TOK '(' Expr ',' Expr ')'
+ {
+ unsigned int width = $3->GetValueWidth();
+ if (width != $5->GetValueWidth()) {
+ yyerror("Width mismatch in NOR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNOR, width, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $3;
+ delete $5;
+ }
+ | BVXNOR_TOK '(' Expr ',' Expr ')'
+ {
+ unsigned int width = $3->GetValueWidth();
+ if (width != $5->GetValueWidth()) {
+ yyerror("Width mismatch in NOR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXNOR, width, *$3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $3;
+ delete $5;
+ }
+ | BVSX_TOK '(' Expr ',' NUMERAL_TOK ')'
+ {
+ //width of the expr which is being sign
+ //extended. $5 is the resulting length of the
+ //signextended expr
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+ if($3->GetValueWidth() == $5) {
+ $$ = $3;
+ }
+ else {
+ BEEV::ASTNode width = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$5);
+ BEEV::ASTNode *n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSX, $5,*$3,width));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ }
+ }
+ | Expr BVCONCAT_TOK Expr
+ {
+ unsigned int width = $1->GetValueWidth() + $3->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, width, *$1, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $1;
+ delete $3;
+ }
+ | Expr BVLEFTSHIFT_TOK NUMERAL_TOK
+ {
+ BEEV::ASTNode zero_bits = BEEV::globalBeevMgr_for_parser->CreateZeroConst($3);
+ BEEV::ASTNode * n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,
+ $1->GetValueWidth() + $3, *$1, zero_bits));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $1;
+ }
+ | Expr BVRIGHTSHIFT_TOK NUMERAL_TOK
+ {
+ BEEV::ASTNode len = BEEV::globalBeevMgr_for_parser->CreateZeroConst($3);
+ unsigned int w = $1->GetValueWidth();
+
+ //the amount by which you are rightshifting
+ //is less-than/equal-to the length of input
+ //bitvector
+ if((unsigned)$3 < w) {
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$3);
+ BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$1,hi,low);
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,len, extract));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ }
+ else
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateZeroConst(w));
+
+ delete $1;
+ }
+ | BVPLUS_TOK '(' NUMERAL_TOK ',' Exprs ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVPLUS, $3, *$5));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $5;
+ }
+ | BVSUB_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSUB, $3, *$5, *$7));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $5;
+ delete $7;
+ }
+ | BVUMINUS_TOK '(' Expr ')'
+ {
+ unsigned width = $3->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVUMINUS,width,*$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ }
+ | BVMULT_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMULT, $3, *$5, *$7));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $5;
+ delete $7;
+ }
+ | BVDIV_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVDIV, $3, *$5, *$7));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $5;
+ delete $7;
+ }
+ | BVMOD_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMOD, $3, *$5, *$7));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $5;
+ delete $7;
+ }
+ | SBVDIV_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::SBVDIV, $3, *$5, *$7));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $5;
+ delete $7;
+ }
+ | SBVMOD_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')'
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::SBVMOD, $3, *$5, *$7));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $5;
+ delete $7;
+ }
+ | IfExpr { $$ = $1; }
+ | ArrayUpdateExpr
+ | LET_TOK LetDecls IN_TOK Expr
+ {
+ $$ = $4;
+ //Cleanup the LetIDToExprMap
+ //BEEV::globalBeevMgr_for_parser->CleanupLetIDMap();
+ }
+ ;
+
+/*Grammar for Array Update Expr*/
+ArrayUpdateExpr : Expr WITH_TOK Updates
+ {
+ BEEV::ASTNode * result;
+ unsigned int width = $1->GetValueWidth();
+
+ BEEV::ASTNodeMap::iterator it = $3->begin();
+ BEEV::ASTNodeMap::iterator itend = $3->end();
+ result = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,
+ width,
+ *$1,
+ (*it).first,
+ (*it).second));
+ result->SetIndexWidth($1->GetIndexWidth());
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*result);
+ for(it++;it!=itend;it++) {
+ result = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,
+ width,
+ *result,
+ (*it).first,
+ (*it).second));
+ result->SetIndexWidth($1->GetIndexWidth());
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*result);
+ }
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*result);
+ $$ = result;
+ delete $3;
+ }
+ ;
+
+Updates : '[' Expr ']' ASSIGN_TOK Expr
+ {
+ $$ = new BEEV::ASTNodeMap();
+ (*$$)[*$2] = *$5;
+ }
+ | Updates WITH_TOK '[' Expr ']' ASSIGN_TOK Expr
+ {
+ (*$1)[*$4] = *$7;
+ }
+ ;
+
+/*Grammar for LET Expr*/
+LetDecls : LetDecl
+ | LetDecls ',' LetDecl
+ ;
+
+LetDecl : FORMID_TOK '=' Expr
+ {
+ //Expr must typecheck
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+
+ //set the valuewidth of the identifier
+ $1->SetValueWidth($3->GetValueWidth());
+ $1->SetIndexWidth($3->GetIndexWidth());
+
+ //populate the hashtable from LET-var -->
+ //LET-exprs and then process them:
+ //
+ //1. ensure that LET variables do not clash
+ //1. with declared variables.
+ //
+ //2. Ensure that LET variables are not
+ //2. defined more than once
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$3);
+ delete $1;
+ delete $3;
+ }
+ | FORMID_TOK ':' Type '=' Expr
+ {
+ //do type checking. if doesn't pass then abort
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+
+ if($3.indexwidth != $5->GetIndexWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+ if($3.valuewidth != $5->GetValueWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+
+ //set the valuewidth of the identifier
+ $1->SetValueWidth($5->GetValueWidth());
+ $1->SetIndexWidth($5->GetIndexWidth());
+
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$5);
+ delete $1;
+ delete $5;
+ }
+ | FORMID_TOK '=' Formula
+ {
+ //Expr must typecheck
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+
+ //set the valuewidth of the identifier
+ $1->SetValueWidth($3->GetValueWidth());
+ $1->SetIndexWidth($3->GetIndexWidth());
+
+ //Do LET-expr management
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$3);
+ delete $1;
+ delete $3;
+ }
+ | FORMID_TOK ':' Type '=' Formula
+ {
+ //do type checking. if doesn't pass then abort
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+
+ if($3.indexwidth != $5->GetIndexWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+ if($3.valuewidth != $5->GetValueWidth())
+ yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+
+ //set the valuewidth of the identifier
+ $1->SetValueWidth($5->GetValueWidth());
+ $1->SetIndexWidth($5->GetIndexWidth());
+
+ //Do LET-expr management
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$5);
+ delete $1;
+ delete $5;
+ }
+ ;
+
+%%
Added: klee/trunk/stp/parser/let-funcs.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/let-funcs.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/parser/let-funcs.cpp (added)
+++ klee/trunk/stp/parser/let-funcs.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,85 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include <stdlib.h>
+
+namespace BEEV {
+ //external parser table for declared symbols. Only symbols which are
+ //declared are stored here.
+ ASTNodeSet _parser_symbol_table;
+
+ // FUNC: This function maintains a map between LET-var names and
+ // LET-expressions
+ //
+ //1. if the Let-var is already defined in the LET scope, then the
+ //1. function returns an error.
+ //
+ //2. if the Let-var is already declared variable in the input, then
+ //2. the function returns an error
+ //
+ //3. otherwise add the <var,letExpr> pair to the _letid_expr table.
+ void BeevMgr::LetExprMgr(const ASTNode& var, const ASTNode& letExpr) {
+ ASTNodeMap::iterator it;
+ if(((it = _letid_expr_map.find(var)) != _letid_expr_map.end()) &&
+ it->second != ASTUndefined) {
+ FatalError("LetExprMgr:The LET-var v has already been defined in this LET scope: v =", var);
+ }
+
+ if(_parser_symbol_table.find(var) != _parser_symbol_table.end()) {
+ FatalError("LetExprMgr:This var is already declared. cannot redeclare as a letvar: v =", var);
+ }
+
+ _letid_expr_map[var] = letExpr;
+ }
+
+ //this function looksup the "var to letexpr map" and returns the
+ //corresponding letexpr. if there is no letexpr, then it simply
+ //returns the var.
+ ASTNode BeevMgr::ResolveID(const ASTNode& v) {
+ if(v.GetKind() != SYMBOL) {
+ return v;
+ }
+
+ if(_parser_symbol_table.find(v) != _parser_symbol_table.end()) {
+ return v;
+ }
+
+ ASTNodeMap::iterator it;
+ if((it =_letid_expr_map.find(v)) != _letid_expr_map.end()) {
+ if(it->second == ASTUndefined)
+ FatalError("Unresolved Identifier: ",v);
+ else
+ return it->second;
+ }
+
+ //this is to mark the let-var as undefined. the let var is defined
+ //only after the LetExprMgr has completed its work, and until then
+ //'v' is undefined.
+ //
+ //declared variables also get stored in this map, but there value
+ //is ASTUndefined. This is really a hack. I don't know how to get
+ //rid of this hack.
+ _letid_expr_map[v] = ASTUndefined;
+ return v;
+ }
+
+ // This function simply cleans up the LetID -> LetExpr Map.
+ void BeevMgr::CleanupLetIDMap(void) {
+ ASTNodeMap::iterator it = _letid_expr_map.begin();
+ ASTNodeMap::iterator itend = _letid_expr_map.end();
+ for(;it!=itend;it++) {
+ if(it->second != ASTUndefined) {
+ it->first.SetValueWidth(0);
+ it->first.SetIndexWidth(0);
+ }
+ }
+ _letid_expr_map.clear();
+ }
+};
Added: klee/trunk/stp/parser/main.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/main.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/parser/main.cpp (added)
+++ klee/trunk/stp/parser/main.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,181 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <algorithm>
+#include <ctime>
+#include <unistd.h>
+#include <signal.h>
+//#include <zlib.h>
+#include <stdio.h>
+#include "../AST/AST.h"
+#include "parsePL_defs.h"
+#include "../sat/Solver.h"
+#include "../sat/SolverTypes.h"
+#include "../sat/VarOrder.h"
+
+#include <unistd.h>
+
+#ifdef EXT_HASH_MAP
+ using namespace __gnu_cxx;
+#endif
+
+/* GLOBAL FUNCTION: parser
+ */
+extern int yyparse();
+//extern int smtlibparse();
+
+/* GLOBAL VARS: Some global vars for the Main function.
+ *
+ */
+const char * prog = "stp";
+int linenum = 1;
+const char * usage = "Usage: %s [-option] [infile]\n";
+std::string helpstring = "\n\n";
+
+// Amount of memory to ask for at beginning of main.
+static const intptr_t INITIAL_MEMORY_PREALLOCATION_SIZE = 4000000;
+
+// Used only in smtlib lexer/parser
+BEEV::ASTNode SingleBitOne;
+BEEV::ASTNode SingleBitZero;
+
+/******************************************************************************
+ * MAIN FUNCTION:
+ *
+ * step 0. Parse the input into an ASTVec.
+ * step 1. Do BV Rewrites
+ * step 2. Bitblasts the ASTNode.
+ * step 3. Convert to CNF
+ * step 4. Convert to SAT
+ * step 5. Call SAT to determine if input is SAT or UNSAT
+ ******************************************************************************/
+int main(int argc, char ** argv) {
+ char * infile;
+ extern FILE *yyin;
+
+ // Grab some memory from the OS upfront to reduce system time when individual
+ // hash tables are being allocated
+
+ if (sbrk(INITIAL_MEMORY_PREALLOCATION_SIZE) == ((void *) -1)) {
+ // FIXME: figure out how to get and print the real error message.
+ BEEV::FatalError("Initial allocation of memory failed.");
+ }
+
+ //populate the help string
+ helpstring += "-r : switch refinement off (optimizations are ON by default)\n";
+ helpstring += "-w : switch wordlevel solver off (optimizations are ON by default)\n";
+ helpstring += "-a : switch optimizations off (optimizations are ON by default)\n";
+ helpstring += "-s : print function statistics\n";
+ helpstring += "-v : print nodes \n";
+ helpstring += "-c : construct counterexample\n";
+ helpstring += "-d : check counterexample\n";
+ helpstring += "-p : print counterexample\n";
+ helpstring += "-x : flatten nested XORs\n";
+ helpstring += "-h : help\n";
+
+ for(int i=1; i < argc;i++) {
+ if(argv[i][0] == '-')
+ switch(argv[i][1]) {
+ case 'a' :
+ BEEV::optimize = false;
+ BEEV::wordlevel_solve = false;
+ break;
+ case 'b':
+ BEEV::print_STPinput_back = true;
+ break;
+ case 'c':
+ BEEV::construct_counterexample = true;
+ break;
+ case 'd':
+ BEEV::construct_counterexample = true;
+ BEEV::check_counterexample = true;
+ break;
+ case 'e':
+ BEEV::variable_activity_optimize = true;
+ break;
+ case 'f':
+ BEEV::smtlib_parser_enable = true;
+ break;
+ case 'h':
+ fprintf(stderr,usage,prog);
+ cout << helpstring;
+ //BEEV::FatalError("");
+ return -1;
+ break;
+ case 'l' :
+ BEEV::linear_search = true;
+ break;
+ case 'n':
+ BEEV::print_output = true;
+ break;
+ case 'p':
+ BEEV::print_counterexample = true;
+ break;
+ case 'q':
+ BEEV::print_arrayval_declaredorder = true;
+ break;
+ case 'r':
+ BEEV::arrayread_refinement = false;
+ break;
+ case 's' :
+ BEEV::stats = true;
+ break;
+ case 'u':
+ BEEV::arraywrite_refinement = false;
+ break;
+ case 'v' :
+ BEEV::print_nodes = true;
+ break;
+ case 'w':
+ BEEV::wordlevel_solve = false;
+ break;
+ case 'x':
+ BEEV::xor_flatten = true;
+ break;
+ case 'z':
+ BEEV::print_sat_varorder = true;
+ break;
+ default:
+ fprintf(stderr,usage,prog);
+ cout << helpstring;
+ //BEEV::FatalError("");
+ return -1;
+ break;
+ }
+ else {
+ infile = argv[i];
+ yyin = fopen(infile,"r");
+ if(yyin == NULL) {
+ fprintf(stderr,"%s: Error: cannot open %s\n",prog,infile);
+ BEEV::FatalError("");
+ }
+ }
+ }
+
+#ifdef NATIVE_C_ARITH
+#else
+ CONSTANTBV::ErrCode c = CONSTANTBV::BitVector_Boot();
+ if(0 != c) {
+ cout << CONSTANTBV::BitVector_Error(c) << endl;
+ return 0;
+ }
+#endif
+
+ //want to print the output always from the commandline.
+ BEEV::print_output = true;
+ BEEV::globalBeevMgr_for_parser = new BEEV::BeevMgr();
+
+ SingleBitOne = BEEV::globalBeevMgr_for_parser->CreateOneConst(1);
+ SingleBitZero = BEEV::globalBeevMgr_for_parser->CreateZeroConst(1);
+ //BEEV::smtlib_parser_enable = true;
+ yyparse();
+}//end of Main
Added: klee/trunk/stp/parser/smtlib.lex
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/smtlib.lex?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/parser/smtlib.lex (added)
+++ klee/trunk/stp/parser/smtlib.lex Wed May 20 23:36:41 2009
@@ -0,0 +1,232 @@
+%{
+ /********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: July, 2006
+ *
+ * This file is modified version of the CVCL's smtlib.lex file. Please
+ * see CVCL license below
+ ********************************************************************/
+
+ /********************************************************************
+ * \file smtlib.lex
+ *
+ * Author: Sergey Berezin, Clark Barrett
+ *
+ * Created: Apr 30 2005
+ *
+ * <hr>
+ * Copyright (C) 2004 by the Board of Trustees of Leland Stanford
+ * Junior University and by New York University.
+ *
+ * License to use, copy, modify, sell and/or distribute this software
+ * and its documentation for any purpose is hereby granted without
+ * royalty, subject to the terms and conditions defined in the \ref
+ * LICENSE file provided with this distribution. In particular:
+ *
+ * - The above copyright notice and this permission notice must appear
+ * in all copies of the software and related documentation.
+ *
+ * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
+ * EXPRESSED OR IMPLIED. USE IT AT YOUR OWN RISK.
+ *
+ * <hr>
+ ********************************************************************/
+ // -*- c++ -*-
+#include <iostream>
+#include "../AST/AST.h"
+#include "parsePL_defs.h"
+
+ extern char *yytext;
+ extern int yyerror (char *msg);
+
+ // File-static (local to this file) variables and functions
+ static std::string _string_lit;
+
+ static char escapeChar(char c) {
+ switch(c) {
+ case 'n': return '\n';
+ case 't': return '\t';
+ default: return c;
+ }
+ }
+
+ extern BEEV::ASTNode SingleBitOne;
+ extern BEEV::ASTNode SingleBitZero;
+
+/* Changed for smtlib speedup */
+/* bv{DIGIT}+ { yylval.node = new BEEV::ASTNode(BEEV::_bm->CreateBVConst(yytext+2, 10)); return BVCONST_TOK;} */
+
+%}
+
+%option noyywrap
+%option nounput
+%option noreject
+%option noyymore
+%option yylineno
+
+%x COMMENT
+%x STRING_LITERAL
+%x USER_VALUE
+
+LETTER ([a-zA-Z])
+DIGIT ([0-9])
+OPCHAR (['\.\_])
+ANYTHING ({LETTER}|{DIGIT}|{OPCHAR})
+
+%%
+[ \n\t\r\f] { /* sk'ip whitespace */ }
+{DIGIT}+ { yylval.uintval = strtoul(yytext, NULL, 10); return NUMERAL_TOK; }
+
+
+bv{DIGIT}+ { yylval.ullval = strtoull(yytext+2, NULL, 10); return BVCONST_TOK; }
+
+bit{DIGIT}+ {
+ char c = yytext[3];
+ if (c == '1') {
+ yylval.node = new BEEV::ASTNode(SingleBitOne);
+ }
+ else {
+ yylval.node = new BEEV::ASTNode(SingleBitZero);
+ }
+ return BITCONST_TOK;
+ };
+
+
+";" { BEGIN COMMENT; }
+<COMMENT>"\n" { BEGIN INITIAL; /* return to normal mode */}
+<COMMENT>. { /* stay in comment mode */ }
+
+<INITIAL>"\"" { BEGIN STRING_LITERAL;
+ _string_lit.erase(_string_lit.begin(),
+ _string_lit.end()); }
+<STRING_LITERAL>"\\". { /* escape characters (like \n or \") */
+ _string_lit.insert(_string_lit.end(),
+ escapeChar(yytext[1])); }
+<STRING_LITERAL>"\"" { BEGIN INITIAL; /* return to normal mode */
+ yylval.str = new std::string(_string_lit);
+ return STRING_TOK; }
+<STRING_LITERAL>. { _string_lit.insert(_string_lit.end(),*yytext); }
+
+
+<INITIAL>"{" { BEGIN USER_VALUE;
+ _string_lit.erase(_string_lit.begin(),
+ _string_lit.end()); }
+<USER_VALUE>"\\"[{}] { /* escape characters */
+ _string_lit.insert(_string_lit.end(),yytext[1]); }
+
+<USER_VALUE>"}" { BEGIN INITIAL; /* return to normal mode */
+ yylval.str = new std::string(_string_lit);
+ return USER_VAL_TOK; }
+<USER_VALUE>"\n" { _string_lit.insert(_string_lit.end(),'\n');}
+<USER_VALUE>. { _string_lit.insert(_string_lit.end(),*yytext); }
+
+"BitVec" { return BITVEC_TOK;}
+"Array" { return ARRAY_TOK;}
+"true" { return TRUE_TOK; }
+"false" { return FALSE_TOK; }
+"not" { return NOT_TOK; }
+"implies" { return IMPLIES_TOK; }
+"ite" { return ITE_TOK;}
+"if_then_else" { return IF_THEN_ELSE_TOK; }
+"and" { return AND_TOK; }
+"or" { return OR_TOK; }
+"xor" { return XOR_TOK; }
+"iff" { return IFF_TOK; }
+"let" { return LET_TOK; }
+"flet" { return FLET_TOK; }
+"notes" { return NOTES_TOK; }
+"cvc_command" { return CVC_COMMAND_TOK; }
+"sorts" { return SORTS_TOK; }
+"funs" { return FUNS_TOK; }
+"preds" { return PREDS_TOK; }
+"extensions" { return EXTENSIONS_TOK; }
+"definition" { return DEFINITION_TOK; }
+"axioms" { return AXIOMS_TOK; }
+"logic" { return LOGIC_TOK; }
+"sat" { return SAT_TOK; }
+"unsat" { return UNSAT_TOK; }
+"unknown" { return UNKNOWN_TOK; }
+"assumption" { return ASSUMPTION_TOK; }
+"formula" { return FORMULA_TOK; }
+"status" { return STATUS_TOK; }
+"difficulty" { return DIFFICULTY_TOK; }
+"benchmark" { return BENCHMARK_TOK; }
+"source" { return SOURCE_TOK;}
+"category" { return CATEGORY_TOK;}
+"extrasorts" { return EXTRASORTS_TOK; }
+"extrafuns" { return EXTRAFUNS_TOK; }
+"extrapreds" { return EXTRAPREDS_TOK; }
+"language" { return LANGUAGE_TOK; }
+"distinct" { return DISTINCT_TOK; }
+"select" { return SELECT_TOK; }
+"store" { return STORE_TOK; }
+":" { return COLON_TOK; }
+"\[" { return LBRACKET_TOK; }
+"\]" { return RBRACKET_TOK; }
+"(" { return LPAREN_TOK; }
+")" { return RPAREN_TOK; }
+"$" { return DOLLAR_TOK; }
+"?" { return QUESTION_TOK; }
+"=" {return EQ_TOK;}
+
+"nand" { return NAND_TOK;}
+"nor" { return NOR_TOK;}
+"/=" { return NEQ_TOK; }
+ ":=" { return ASSIGN_TOK;}
+"shift_left0" { return BVLEFTSHIFT_TOK;}
+"bvshl" { return BVLEFTSHIFT_1_TOK;}
+"shift_right0" { return BVRIGHTSHIFT_TOK;}
+"bvlshr" { return BVRIGHTSHIFT_1_TOK;}
+"bvadd" { return BVPLUS_TOK;}
+"bvsub" { return BVSUB_TOK;}
+"bvnot" { return BVNOT_TOK;}
+"bvmul" { return BVMULT_TOK;}
+"bvdiv" { return BVDIV_TOK;}
+"bvmod" { return BVMOD_TOK;}
+"bvneg" { return BVNEG_TOK;}
+"bvand" { return BVAND_TOK;}
+"bvor" { return BVOR_TOK;}
+"bvxor" { return BVXOR_TOK;}
+"bvnand" { return BVNAND_TOK;}
+"bvnor" { return BVNOR_TOK;}
+"bvxnor" { return BVXNOR_TOK;}
+"concat" { return BVCONCAT_TOK;}
+"extract" { return BVEXTRACT_TOK;}
+"bvlt" { return BVLT_TOK;}
+"bvgt" { return BVGT_TOK;}
+"bvleq" { return BVLE_TOK;}
+"bvgeq" { return BVGE_TOK;}
+"bvult" { return BVLT_TOK;}
+"bvugt" { return BVGT_TOK;}
+"bvuleq" { return BVLE_TOK;}
+"bvugeq" { return BVGE_TOK;}
+"bvule" { return BVLE_TOK;}
+"bvuge" { return BVGE_TOK;}
+
+"bvslt" { return BVSLT_TOK;}
+"bvsgt" { return BVSGT_TOK;}
+"bvsleq" { return BVSLE_TOK;}
+"bvsgeq" { return BVSGE_TOK;}
+"bvsle" { return BVSLE_TOK;}
+"bvsge" { return BVSGE_TOK;}
+
+"sign_extend" { return BVSX_TOK;}
+"boolextract" { return BOOLEXTRACT_TOK;}
+"boolbv" { return BOOL_TO_BV_TOK;}
+
+(({LETTER})|(_)({ANYTHING}))({ANYTHING})* {
+ BEEV::ASTNode nptr = BEEV::globalBeevMgr_for_parser->CreateSymbol(yytext);
+
+ // Check valuesize to see if it's a prop var. I don't like doing
+ // type determination in the lexer, but it's easier than rewriting
+ // the whole grammar to eliminate the term/formula distinction.
+ yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(nptr));
+ //yylval.node = new BEEV::ASTNode(nptr);
+ if ((yylval.node)->GetType() == BEEV::BOOLEAN_TYPE)
+ return FORMID_TOK;
+ else
+ return TERMID_TOK;
+}
+. { yyerror("Illegal input character."); }
+%%
Added: klee/trunk/stp/parser/smtlib.y
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/parser/smtlib.y?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/parser/smtlib.y (added)
+++ klee/trunk/stp/parser/smtlib.y Wed May 20 23:36:41 2009
@@ -0,0 +1,1036 @@
+%{
+ /********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: July, 2006
+ *
+ * This file is modified version of the CVCL's smtlib.y file. Please
+ * see CVCL license below
+ ********************************************************************/
+
+ /********************************************************************
+ *
+ * \file smtlib.y
+ *
+ * Author: Sergey Berezin, Clark Barrett
+ *
+ * Created: Apr 30 2005
+ *
+ * <hr>
+ * Copyright (C) 2004 by the Board of Trustees of Leland Stanford
+ * Junior University and by New York University.
+ *
+ * License to use, copy, modify, sell and/or distribute this software
+ * and its documentation for any purpose is hereby granted without
+ * royalty, subject to the terms and conditions defined in the \ref
+ * LICENSE file provided with this distribution. In particular:
+ *
+ * - The above copyright notice and this permission notice must appear
+ * in all copies of the software and related documentation.
+ *
+ * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
+ * EXPRESSED OR IMPLIED. USE IT AT YOUR OWN RISK.
+ *
+ * <hr>
+ ********************************************************************/
+ // -*- c++ -*-
+
+#include "../AST/AST.h"
+ using namespace std;
+
+ // Suppress the bogus warning suppression in bison (it generates
+ // compile error)
+#undef __GNUC_MINOR__
+
+ extern char* yytext;
+ extern int yylineno;
+
+ //int yylineno;
+
+ extern int yylex(void);
+
+ int yyerror(char *s) {
+ //yylineno = 0;
+ cout << "syntax error: line " << yylineno << "\n" << s << endl;
+ cout << " token: " << yytext << endl;
+ BEEV::FatalError("");
+ return 1;
+ }
+
+ BEEV::ASTNode query;
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYMAXDEPTH 104857600
+#define YYERROR_VERBOSE 1
+#define YY_EXIT_FAILURE -1
+%}
+
+%union {
+ // FIXME: Why is this not an UNSIGNED int?
+ int uintval; /* for numerals in types. */
+
+ // for BV32 BVCONST
+ unsigned long long ullval;
+
+ struct {
+ //stores the indexwidth and valuewidth
+ //indexwidth is 0 iff type is bitvector. positive iff type is
+ //array, and stores the width of the indexing bitvector
+ unsigned int indexwidth;
+ //width of the bitvector type
+ unsigned int valuewidth;
+ } indexvaluewidth;
+
+ //ASTNode,ASTVec
+ BEEV::ASTNode *node;
+ BEEV::ASTVec *vec;
+ std::string *str;
+};
+
+%start cmd
+
+%type <indexvaluewidth> sort_symb sort_symbs
+%type <node> status
+%type <vec> bench_attributes an_formulas
+
+%type <node> benchmark bench_name bench_attribute
+%type <node> an_term an_nonbvconst_term an_formula
+
+%type <node> var fvar logic_name
+%type <str> user_value
+
+%token <uintval> NUMERAL_TOK
+%token <ullval> BVCONST_TOK
+%token <node> BITCONST_TOK
+%token <node> FORMID_TOK TERMID_TOK
+%token <str> STRING_TOK
+%token <str> USER_VAL_TOK
+%token SOURCE_TOK
+%token CATEGORY_TOK
+%token DIFFICULTY_TOK
+%token BITVEC_TOK
+%token ARRAY_TOK
+%token SELECT_TOK
+%token STORE_TOK
+%token TRUE_TOK
+%token FALSE_TOK
+%token NOT_TOK
+%token IMPLIES_TOK
+%token ITE_TOK
+%token IF_THEN_ELSE_TOK
+%token AND_TOK
+%token OR_TOK
+%token XOR_TOK
+%token IFF_TOK
+%token EXISTS_TOK
+%token FORALL_TOK
+%token LET_TOK
+%token FLET_TOK
+%token NOTES_TOK
+%token CVC_COMMAND_TOK
+%token SORTS_TOK
+%token FUNS_TOK
+%token PREDS_TOK
+%token EXTENSIONS_TOK
+%token DEFINITION_TOK
+%token AXIOMS_TOK
+%token LOGIC_TOK
+%token COLON_TOK
+%token LBRACKET_TOK
+%token RBRACKET_TOK
+%token LPAREN_TOK
+%token RPAREN_TOK
+%token SAT_TOK
+%token UNSAT_TOK
+%token UNKNOWN_TOK
+%token ASSUMPTION_TOK
+%token FORMULA_TOK
+%token STATUS_TOK
+%token BENCHMARK_TOK
+%token EXTRASORTS_TOK
+%token EXTRAFUNS_TOK
+%token EXTRAPREDS_TOK
+%token LANGUAGE_TOK
+%token DOLLAR_TOK
+%token QUESTION_TOK
+%token DISTINCT_TOK
+%token SEMICOLON_TOK
+%token EOF_TOK
+%token EQ_TOK
+/*BV SPECIFIC TOKENS*/
+%token NAND_TOK
+%token NOR_TOK
+%token NEQ_TOK
+%token ASSIGN_TOK
+%token BV_TOK
+%token BOOLEAN_TOK
+%token BVLEFTSHIFT_TOK
+%token BVLEFTSHIFT_1_TOK
+%token BVRIGHTSHIFT_TOK
+%token BVRIGHTSHIFT_1_TOK
+%token BVPLUS_TOK
+%token BVSUB_TOK
+%token BVNOT_TOK //bvneg in CVCL
+%token BVMULT_TOK
+%token BVDIV_TOK
+%token BVMOD_TOK
+%token BVNEG_TOK //bvuminus in CVCL
+%token BVAND_TOK
+%token BVOR_TOK
+%token BVXOR_TOK
+%token BVNAND_TOK
+%token BVNOR_TOK
+%token BVXNOR_TOK
+%token BVCONCAT_TOK
+%token BVLT_TOK
+%token BVGT_TOK
+%token BVLE_TOK
+%token BVGE_TOK
+%token BVSLT_TOK
+%token BVSGT_TOK
+%token BVSLE_TOK
+%token BVSGE_TOK
+%token BVSX_TOK
+%token BOOLEXTRACT_TOK
+%token BOOL_TO_BV_TOK
+%token BVEXTRACT_TOK
+
+%left LBRACKET_TOK RBRACKET_TOK
+
+%%
+
+cmd:
+ benchmark
+ {
+ if($1 != NULL) {
+ BEEV::globalBeevMgr_for_parser->TopLevelSAT(*$1,query);
+ delete $1;
+ }
+ YYACCEPT;
+ }
+;
+
+benchmark:
+ LPAREN_TOK BENCHMARK_TOK bench_name bench_attributes RPAREN_TOK
+ {
+ if($4 != NULL){
+ if($4->size() > 1)
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND,*$4));
+ else
+ $$ = new BEEV::ASTNode((*$4)[0]);
+ delete $4;
+ }
+ else {
+ $$ = NULL;
+ }
+ }
+/* | EOF_TOK */
+/* { */
+/* } */
+;
+
+bench_name:
+ FORMID_TOK
+ {
+ }
+;
+
+bench_attributes:
+ bench_attribute
+ {
+ $$ = new BEEV::ASTVec;
+ if ($1 != NULL) {
+ $$->push_back(*$1);
+ BEEV::globalBeevMgr_for_parser->AddAssert(*$1);
+ delete $1;
+ }
+ }
+ | bench_attributes bench_attribute
+ {
+ if ($1 != NULL && $2 != NULL) {
+ $1->push_back(*$2);
+ BEEV::globalBeevMgr_for_parser->AddAssert(*$2);
+ $$ = $1;
+ delete $2;
+ }
+ }
+;
+
+bench_attribute:
+ COLON_TOK ASSUMPTION_TOK an_formula
+ {
+ //assumptions are like asserts
+ $$ = $3;
+ }
+ | COLON_TOK FORMULA_TOK an_formula
+ {
+ //the query
+ query = BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT,*$3);
+ BEEV::globalBeevMgr_for_parser->AddQuery(query);
+ //dummy true
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE));
+
+
+ }
+ | COLON_TOK STATUS_TOK status
+ {
+ $$ = NULL;
+ }
+ | COLON_TOK LOGIC_TOK logic_name
+ {
+ if (!(0 == strcmp($3->GetName(),"QF_UFBV") ||
+ 0 == strcmp($3->GetName(),"QF_AUFBV"))) {
+ yyerror("Wrong input logic:");
+ }
+ $$ = NULL;
+ }
+ | COLON_TOK EXTRAFUNS_TOK LPAREN_TOK var_decls RPAREN_TOK
+ {
+ $$ = NULL;
+ }
+ | COLON_TOK EXTRAPREDS_TOK LPAREN_TOK var_decls RPAREN_TOK
+ {
+ $$ = NULL;
+ }
+ | annotation
+ {
+ $$ = NULL;
+ }
+;
+
+logic_name:
+ FORMID_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK
+ {
+ $$ = $1;
+ }
+ | FORMID_TOK
+ {
+ $$ = $1;
+ }
+;
+
+status:
+ SAT_TOK { $$ = NULL; }
+ | UNSAT_TOK { $$ = NULL; }
+ | UNKNOWN_TOK { $$ = NULL; }
+;
+
+
+/* annotations: */
+/* annotation */
+/* { */
+/* } */
+/* | annotations annotation */
+/* { */
+/* } */
+/* ; */
+
+annotation:
+ attribute
+ {
+ }
+ | attribute user_value
+ {
+ }
+;
+
+user_value:
+ USER_VAL_TOK
+ {
+ //cerr << "Printing user_value: " << *$1 << endl;
+ }
+;
+
+attribute:
+ COLON_TOK SOURCE_TOK
+ {
+ }
+ | COLON_TOK CATEGORY_TOK
+ {
+ }
+ | COLON_TOK DIFFICULTY_TOK
+;
+
+sort_symbs:
+ sort_symb
+ {
+ //a single sort symbol here means either a BitVec or a Boolean
+ $$.indexwidth = $1.indexwidth;
+ $$.valuewidth = $1.valuewidth;
+ }
+ | sort_symb sort_symb
+ {
+ //two sort symbols mean f: type --> type
+ $$.indexwidth = $1.valuewidth;
+ $$.valuewidth = $2.valuewidth;
+ }
+;
+
+var_decls:
+ var_decl
+ {
+ }
+// | LPAREN_TOK var_decl RPAREN_TOK
+ |
+ var_decls var_decl
+ {
+ }
+;
+
+var_decl:
+ LPAREN_TOK FORMID_TOK sort_symbs RPAREN_TOK
+ {
+ BEEV::_parser_symbol_table.insert(*$2);
+ //Sort_symbs has the indexwidth/valuewidth. Set those fields in
+ //var
+ $2->SetIndexWidth($3.indexwidth);
+ $2->SetValueWidth($3.valuewidth);
+ }
+ | LPAREN_TOK FORMID_TOK RPAREN_TOK
+ {
+ BEEV::_parser_symbol_table.insert(*$2);
+ //Sort_symbs has the indexwidth/valuewidth. Set those fields in
+ //var
+ $2->SetIndexWidth(0);
+ $2->SetValueWidth(0);
+ }
+;
+
+an_formulas:
+ an_formula
+ {
+ $$ = new BEEV::ASTVec;
+ if ($1 != NULL) {
+ $$->push_back(*$1);
+ delete $1;
+ }
+ }
+ |
+ an_formulas an_formula
+ {
+ if ($1 != NULL && $2 != NULL) {
+ $1->push_back(*$2);
+ $$ = $1;
+ delete $2;
+ }
+ }
+;
+
+an_formula:
+ TRUE_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE));
+ $$->SetIndexWidth(0);
+ $$->SetValueWidth(0);
+ }
+ | FALSE_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::FALSE));
+ $$->SetIndexWidth(0);
+ $$->SetValueWidth(0);
+ }
+ | fvar
+ {
+ $$ = $1;
+ }
+ | LPAREN_TOK EQ_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK EQ_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateSimplifiedEQ(*$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVSLT_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVSLT_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLT, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVSLE_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVSLE_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLE, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVSGT_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVSGT_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGT, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVSGE_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVSGE_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGE, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVLT_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVLT_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLT, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVLE_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVLE_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLE, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVGT_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVGT_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGT, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK BVGE_TOK an_term an_term RPAREN_TOK
+ //| LPAREN_TOK BVGE_TOK an_term an_term annotations RPAREN_TOK
+ {
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGE, *$3, *$4));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK an_formula RPAREN_TOK
+ {
+ $$ = $2;
+ }
+ | LPAREN_TOK NOT_TOK an_formula RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT, *$3));
+ delete $3;
+ }
+ | LPAREN_TOK IMPLIES_TOK an_formula an_formula RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IMPLIES, *$3, *$4));
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK IF_THEN_ELSE_TOK an_formula an_formula an_formula RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$3, *$4, *$5));
+ delete $3;
+ delete $4;
+ delete $5;
+ }
+ | LPAREN_TOK AND_TOK an_formulas RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND, *$3));
+ delete $3;
+ }
+ | LPAREN_TOK OR_TOK an_formulas RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::OR, *$3));
+ delete $3;
+ }
+ | LPAREN_TOK XOR_TOK an_formula an_formula RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::XOR, *$3, *$4));
+ delete $3;
+ delete $4;
+ }
+ | LPAREN_TOK IFF_TOK an_formula an_formula RPAREN_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IFF, *$3, *$4));
+ delete $3;
+ delete $4;
+ }
+ | letexpr_mgmt an_formula RPAREN_TOK
+ //| letexpr_mgmt an_formula annotations RPAREN_TOK
+ {
+ $$ = $2;
+ //Cleanup the LetIDToExprMap
+ BEEV::globalBeevMgr_for_parser->CleanupLetIDMap();
+ }
+;
+
+letexpr_mgmt:
+ LPAREN_TOK LET_TOK LPAREN_TOK QUESTION_TOK FORMID_TOK an_term RPAREN_TOK
+ {
+ //Expr must typecheck
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$6);
+
+ //set the valuewidth of the identifier
+ $5->SetValueWidth($6->GetValueWidth());
+ $5->SetIndexWidth($6->GetIndexWidth());
+
+ //populate the hashtable from LET-var -->
+ //LET-exprs and then process them:
+ //
+ //1. ensure that LET variables do not clash
+ //1. with declared variables.
+ //
+ //2. Ensure that LET variables are not
+ //2. defined more than once
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*$5,*$6);
+ delete $5;
+ delete $6;
+ }
+ | LPAREN_TOK FLET_TOK LPAREN_TOK DOLLAR_TOK FORMID_TOK an_formula RPAREN_TOK
+ {
+ //Expr must typecheck
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$6);
+
+ //set the valuewidth of the identifier
+ $5->SetValueWidth($6->GetValueWidth());
+ $5->SetIndexWidth($6->GetIndexWidth());
+
+ //Do LET-expr management
+ BEEV::globalBeevMgr_for_parser->LetExprMgr(*$5,*$6);
+ delete $5;
+ delete $6;
+ }
+
+/* an_terms: */
+/* an_term */
+/* { */
+/* } */
+/* | an_terms an_term */
+/* { */
+/* } */
+/* ; */
+
+an_term:
+ BVCONST_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(64, $1));
+ }
+ | BVCONST_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst($3, $1));
+ }
+ | an_nonbvconst_term
+ ;
+
+an_nonbvconst_term:
+ BITCONST_TOK { $$ = $1; }
+ | var
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1));
+ delete $1;
+ }
+ | LPAREN_TOK an_term RPAREN_TOK
+ //| LPAREN_TOK an_term annotations RPAREN_TOK
+ {
+ $$ = $2;
+ //$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->SimplifyTerm(*$2));
+ //delete $2;
+ }
+ | LPAREN_TOK TERMID_TOK an_term RPAREN_TOK
+ {
+ //ARRAY READ
+ // valuewidth is same as array, indexwidth is 0.
+ BEEV::ASTNode in = *$2;
+ BEEV::ASTNode m = *$3;
+ unsigned int width = in.GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, in, m));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | SELECT_TOK an_term an_term
+ {
+ //ARRAY READ
+ // valuewidth is same as array, indexwidth is 0.
+ BEEV::ASTNode array = *$2;
+ BEEV::ASTNode index = *$3;
+ unsigned int width = array.GetValueWidth();
+ BEEV::ASTNode * n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, array, index));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | STORE_TOK an_term an_term an_term
+ {
+ //ARRAY WRITE
+ unsigned int width = $4->GetValueWidth();
+ BEEV::ASTNode array = *$2;
+ BEEV::ASTNode index = *$3;
+ BEEV::ASTNode writeval = *$4;
+ BEEV::ASTNode write_term = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,width,array,index,writeval);
+ write_term.SetIndexWidth($2->GetIndexWidth());
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(write_term);
+ BEEV::ASTNode * n = new BEEV::ASTNode(write_term);
+ $$ = n;
+ delete $2;
+ delete $3;
+ delete $4;
+ }
+/* | BVEXTRACT_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK BVCONST_TOK */
+/* { */
+/* // This special case is when we have an extract on top of a constant bv, which happens */
+/* // almost all the time in the smt syntax. */
+
+/* // $3 is high, $5 is low. They are ints (why not unsigned? See uintval) */
+/* int hi = $3; */
+/* int low = $5; */
+/* int width = hi - low + 1; */
+
+/* if (width < 0) */
+/* yyerror("Negative width in extract"); */
+
+/* unsigned long long int val = $7; */
+
+/* // cut and past from BV32 const evaluator */
+
+/* unsigned long long int mask1 = 0xffffffffffffffffLL; */
+
+/* mask1 >>= 64-(hi+1); */
+
+/* //extract val[hi:0] */
+/* val &= mask1; */
+/* //extract val[hi:low] */
+/* val >>= low; */
+
+/* // val is the desired BV32. */
+/* BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(width, val)); */
+/* $$ = n; */
+/* } */
+ | BVEXTRACT_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK an_term
+ {
+ int width = $3 - $5 + 1;
+ if (width < 0)
+ yyerror("Negative width in extract");
+
+ if((unsigned)$3 >= $7->GetValueWidth() || (unsigned)$5 < 0)
+ yyerror("Parsing: Wrong width in BVEXTRACT\n");
+
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $3);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+ BEEV::ASTNode output = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT, width, *$7,hi,low);
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->SimplifyTerm(output));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $7;
+ }
+ | ITE_TOK an_formula an_term an_term
+ {
+ unsigned int width = $3->GetValueWidth();
+ if (width != $4->GetValueWidth()) {
+ cerr << *$3;
+ cerr << *$4;
+ yyerror("Width mismatch in IF-THEN-ELSE");
+ }
+ if($3->GetIndexWidth() != $4->GetIndexWidth())
+ yyerror("Width mismatch in IF-THEN-ELSE");
+
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4);
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateSimplifiedTermITE(*$2, *$3, *$4));
+ //$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE,width,*$2, *$3, *$4));
+ $$->SetIndexWidth($4->GetIndexWidth());
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$);
+ delete $2;
+ delete $3;
+ delete $4;
+ }
+ | BVCONCAT_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth() + $3->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+
+ delete $2;
+ delete $3;
+ }
+ | BVNOT_TOK an_term
+ {
+ //this is the BVNEG (term) in the CVCL language
+ unsigned int width = $2->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNEG, width, *$2));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ }
+ | BVNEG_TOK an_term
+ {
+ //this is the BVUMINUS term in CVCL langauge
+ unsigned width = $2->GetValueWidth();
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVUMINUS,width,*$2));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ }
+ | BVAND_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in AND");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVAND, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVOR_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in OR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVOR, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVXOR_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in XOR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXOR, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVSUB_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in BVSUB");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSUB, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVPLUS_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in BVPLUS");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVPLUS, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+
+ }
+ | BVMULT_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in BVMULT");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMULT, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVNAND_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in BVNAND");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNAND, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVNOR_TOK an_term an_term
+ {
+ unsigned int width = $2->GetValueWidth();
+ if (width != $3->GetValueWidth()) {
+ yyerror("Width mismatch in BVNOR");
+ }
+ BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNOR, width, *$2, *$3));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $2;
+ delete $3;
+ }
+ | BVLEFTSHIFT_TOK an_term NUMERAL_TOK
+ {
+ unsigned int w = $2->GetValueWidth();
+ if((unsigned)$3 < w) {
+ BEEV::ASTNode trailing_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst($3, 0);
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, w-$3-1);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,0);
+ BEEV::ASTNode m = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$2,hi,low);
+ BEEV::ASTNode * n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,w,m,trailing_zeros));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ }
+ else
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+ delete $2;
+ }
+ | BVLEFTSHIFT_1_TOK an_term an_term
+ {
+ unsigned int w = $2->GetValueWidth();
+ unsigned int shift_amt = GetUnsignedConst(*$3);
+ if((unsigned)shift_amt < w) {
+ BEEV::ASTNode trailing_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst(shift_amt, 0);
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, w-shift_amt-1);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,0);
+ BEEV::ASTNode m = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-shift_amt,*$2,hi,low);
+ BEEV::ASTNode * n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,w,m,trailing_zeros));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ }
+ else {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+ }
+ delete $2;
+ //delete $3;
+ }
+ | BVRIGHTSHIFT_TOK an_term NUMERAL_TOK
+ {
+ BEEV::ASTNode leading_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst($3, 0);
+ unsigned int w = $2->GetValueWidth();
+
+ //the amount by which you are rightshifting
+ //is less-than/equal-to the length of input
+ //bitvector
+ if((unsigned)$3 < w) {
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$3);
+ BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$2,hi,low);
+ BEEV::ASTNode * n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,leading_zeros, extract));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ }
+ else {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+ }
+ delete $2;
+ }
+ | BVRIGHTSHIFT_1_TOK an_term an_term
+ {
+ unsigned int shift_amt = GetUnsignedConst(*$3);
+ BEEV::ASTNode leading_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst(shift_amt, 0);
+ unsigned int w = $2->GetValueWidth();
+
+ //the amount by which you are rightshifting
+ //is less-than/equal-to the length of input
+ //bitvector
+ if((unsigned)shift_amt < w) {
+ BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1);
+ BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,shift_amt);
+ BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-shift_amt,*$2,hi,low);
+ BEEV::ASTNode * n =
+ new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,leading_zeros, extract));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ }
+ else {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+ }
+ delete $2;
+ }
+ | BVSX_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK an_term
+ {
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+ unsigned w = $5->GetValueWidth() + $3;
+ BEEV::ASTNode width = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w);
+ BEEV::ASTNode *n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSX,w,*$5,width));
+ BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+ $$ = n;
+ delete $5;
+ }
+;
+
+sort_symb:
+ BITVEC_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK
+ {
+ // Just return BV width. If sort is BOOL, width is 0.
+ // Otherwise, BITVEC[w] returns w.
+ //
+ //((indexwidth is 0) && (valuewidth>0)) iff type is BV
+ $$.indexwidth = 0;
+ unsigned int length = $3;
+ if(length > 0) {
+ $$.valuewidth = length;
+ }
+ else {
+ BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+ }
+ }
+ | ARRAY_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK
+ {
+ unsigned int index_len = $3;
+ unsigned int value_len = $5;
+ if(index_len > 0) {
+ $$.indexwidth = $3;
+ }
+ else {
+ BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+ }
+
+ if(value_len > 0) {
+ $$.valuewidth = $5;
+ }
+ else {
+ BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+ }
+ }
+;
+
+var:
+ FORMID_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1));
+ delete $1;
+ }
+ | TERMID_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1));
+ delete $1;
+ }
+ | QUESTION_TOK TERMID_TOK
+ {
+ $$ = $2;
+ }
+;
+
+fvar:
+ DOLLAR_TOK FORMID_TOK
+ {
+ $$ = $2;
+ }
+ | FORMID_TOK
+ {
+ $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1));
+ delete $1;
+ }
+;
+%%
Added: klee/trunk/stp/sat/Global.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Global.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Global.h (added)
+++ klee/trunk/stp/sat/Global.h Wed May 20 23:36:41 2009
@@ -0,0 +1,255 @@
+/****************************************************************************************[Global.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Global_h
+#define Global_h
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <new>
+
+// PKT: needs to be outside namespace MINISAT or mac os x compilation breaks
+#ifdef _MSC_VER
+#else
+#include <unistd.h>
+#endif
+
+namespace MINISAT {
+//=================================================================================================
+// Basic Types & Minor Things:
+
+// DWD: This is needed on darwin.
+typedef unsigned int uint;
+
+#ifdef _MSC_VER
+
+typedef INT64 int64;
+typedef UINT64 uint64;
+typedef INT_PTR intp;
+typedef UINT_PTR uintp;
+#define I64_fmt "I64d"
+#else
+
+typedef long long int64;
+typedef unsigned long long uint64;
+typedef __PTRDIFF_TYPE__ intp;
+typedef unsigned __PTRDIFF_TYPE__ uintp;
+#define I64_fmt "lld"
+#endif
+
+template<class T> static inline T min(T x, T y) { return (x < y) ? x : y; }
+template<class T> static inline T max(T x, T y) { return (x > y) ? x : y; }
+
+template <bool> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true>{};
+#define TEMPLATE_FAIL STATIC_ASSERTION_FAILURE<false>()
+
+
+//=================================================================================================
+// 'malloc()'-style memory allocation -- never returns NULL; aborts instead:
+
+
+template<class T> static inline T* xmalloc(size_t size) {
+ T* tmp = (T*)malloc(size * sizeof(T));
+ assert(size == 0 || tmp != NULL);
+ return tmp; }
+
+template<class T> static inline T* xrealloc(T* ptr, size_t size) {
+ T* tmp = (T*)realloc((void*)ptr, size * sizeof(T));
+ assert(size == 0 || tmp != NULL);
+ return tmp; }
+
+template<class T> static inline void xfree(T *ptr) {
+ if (ptr != NULL) free((void*)ptr); }
+
+
+//=================================================================================================
+// Random numbers:
+
+
+// Returns a random float 0 <= x < 1. Seed must never be 0.
+static inline double drand(double& seed) {
+ seed *= 1389796;
+ int q = (int)(seed / 2147483647);
+ seed -= (double)q * 2147483647;
+ return seed / 2147483647; }
+
+// Returns a random integer 0 <= x < size. Seed must never be 0.
+static inline int irand(double& seed, int size) {
+ return (int)(drand(seed) * size); }
+
+
+//=================================================================================================
+// 'vec' -- automatically resizable arrays (via 'push()' method):
+
+
+// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc)
+
+template<class T>
+class vec {
+ T* data;
+ int sz;
+ int cap;
+
+ void init(int size, const T& pad);
+ void grow(int min_cap);
+
+public:
+ // Types:
+ typedef int Key;
+ typedef T Datum;
+
+ // Constructors:
+ vec(void) : data(NULL) , sz(0) , cap(0) { }
+ vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); }
+ vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); }
+ vec(T* array, int size) : data(array), sz(size), cap(size) { } // (takes ownership of array -- will be deallocated with 'xfree()')
+ ~vec(void) { clear(true); }
+
+ // Ownership of underlying array:
+ T* release (void) { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; }
+ operator T* (void) { return data; } // (unsafe but convenient)
+ operator const T* (void) const { return data; }
+
+ // Size operations:
+ int size (void) const { return sz; }
+ void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); }
+ void pop (void) { sz--, data[sz].~T(); }
+ void growTo (int size);
+ void growTo (int size, const T& pad);
+ void clear (bool dealloc = false);
+ void capacity (int size) { grow(size); }
+
+ // Stack interface:
+ void push (void) { if (sz == cap) grow(sz+1); new (&data[sz]) T() ; sz++; }
+ void push (const T& elem) { if (sz == cap) grow(sz+1); new (&data[sz]) T(elem); sz++; }
+ const T& last (void) const { return data[sz-1]; }
+ T& last (void) { return data[sz-1]; }
+
+ // Vector interface:
+ const T& operator [] (int index) const { return data[index]; }
+ T& operator [] (int index) { return data[index]; }
+
+ // Don't allow copying (error prone):
+ vec<T>& operator = (vec<T>& other) { TEMPLATE_FAIL; }
+ vec (vec<T>& other) { TEMPLATE_FAIL; }
+
+ // Duplicatation (preferred instead):
+ void copyTo(vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) new (©[i]) T(data[i]); }
+ void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; }
+};
+
+template<class T>
+void vec<T>::grow(int min_cap) {
+ if (min_cap <= cap) return;
+ if (cap == 0) cap = (min_cap >= 2) ? min_cap : 2;
+ else do cap = (cap*3+1) >> 1; while (cap < min_cap);
+ data = xrealloc(data, cap); }
+
+template<class T>
+void vec<T>::growTo(int size, const T& pad) {
+ if (sz >= size) return;
+ grow(size);
+ for (int i = sz; i < size; i++) new (&data[i]) T(pad);
+ sz = size; }
+
+template<class T>
+void vec<T>::growTo(int size) {
+ if (sz >= size) return;
+ grow(size);
+ for (int i = sz; i < size; i++) new (&data[i]) T();
+ sz = size; }
+
+template<class T>
+void vec<T>::clear(bool dealloc) {
+ if (data != NULL){
+ for (int i = 0; i < sz; i++) data[i].~T();
+ sz = 0;
+ if (dealloc) xfree(data), data = NULL, cap = 0; } }
+
+
+//=================================================================================================
+// Useful functions on vectors
+
+
+template<class V, class T>
+void remove(V& ts, const T& t)
+{
+ int j = 0;
+ for (; j < ts.size() && ts[j] != t; j++);
+ assert(j < ts.size());
+ for (; j < ts.size()-1; j++) ts[j] = ts[j+1];
+ ts.pop();
+}
+
+
+template<class V, class T>
+bool find(V& ts, const T& t)
+{
+ int j = 0;
+ for (; j < ts.size() && ts[j] != t; j++);
+ return j < ts.size();
+}
+
+//=================================================================================================
+// Lifted booleans:
+
+
+class lbool {
+ int value;
+ explicit lbool(int v) : value(v) { }
+
+public:
+ lbool() : value(0) { }
+ lbool(bool x) : value((int)x*2-1) { }
+ int toInt(void) const { return value; }
+
+ bool operator == (const lbool& other) const { return value == other.value; }
+ bool operator != (const lbool& other) const { return value != other.value; }
+ lbool operator ~ (void) const { return lbool(-value); }
+
+ friend int toInt (lbool l);
+ friend lbool toLbool(int v);
+};
+inline int toInt (lbool l) { return l.toInt(); }
+inline lbool toLbool(int v) { return lbool(v); }
+
+const lbool l_True = toLbool( 1);
+const lbool l_False = toLbool(-1);
+const lbool l_Undef = toLbool( 0);
+
+
+//=================================================================================================
+// Relation operators -- extend definitions from '==' and '<'
+
+
+#ifndef __SGI_STL_INTERNAL_RELOPS // (be aware of SGI's STL implementation...)
+#define __SGI_STL_INTERNAL_RELOPS
+template <class T> static inline bool operator != (const T& x, const T& y) { return !(x == y); }
+template <class T> static inline bool operator > (const T& x, const T& y) { return y < x; }
+template <class T> static inline bool operator <= (const T& x, const T& y) { return !(y < x); }
+template <class T> static inline bool operator >= (const T& x, const T& y) { return !(x < y); }
+#endif
+
+
+//=================================================================================================
+};
+#endif
Added: klee/trunk/stp/sat/Heap.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Heap.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Heap.h (added)
+++ klee/trunk/stp/sat/Heap.h Wed May 20 23:36:41 2009
@@ -0,0 +1,151 @@
+/******************************************************************************************[Heap.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Heap_h
+#define Heap_h
+
+#include "../AST/ASTUtil.h"
+namespace MINISAT {
+
+//=================================================================================================
+
+
+static inline int left (int i) { return i+i; }
+static inline int right (int i) { return i+i + 1; }
+static inline int parent(int i) { return i >> 1; }
+
+template<class C>
+class Heap {
+ public:
+ C comp;
+ vec<int> heap; // heap of ints
+ vec<int> indices; // int -> index in heap
+
+ inline void percolateUp(int i)
+ {
+ int x = heap[i];
+ while (parent(i) != 0 && comp(x,heap[parent(i)])){
+ heap[i] = heap[parent(i)];
+ indices[heap[i]] = i;
+ i = parent(i);
+ }
+ heap [i] = x;
+ indices[x] = i;
+ }
+
+ inline void percolateDown(int i)
+ {
+ int x = heap[i];
+ while (left(i) < heap.size()){
+ int child = right(i) < heap.size() && comp(heap[right(i)],heap[left(i)]) ? right(i) : left(i);
+ if (!comp(heap[child],x)) break;
+ heap[i] = heap[child];
+ indices[heap[i]] = i;
+ i = child;
+ }
+ heap [i] = x;
+ indices[x] = i;
+ }
+
+ bool ok(int n) const {
+ return n >= 0 && n < (int)indices.size(); }
+
+ public:
+ Heap(C c) : comp(c) { heap.push(-1); }
+
+ void setBounds (int size) { assert(size >= 0); indices.growTo(size,0); }
+ void increase (int n) { assert(ok(n)); assert(inHeap(n)); percolateUp(indices[n]); }
+ bool inHeap (int n) const { assert(ok(n)); return indices[n] != 0; }
+ int size () const { return heap.size()-1; }
+ bool empty () const { return size() == 0; }
+
+
+ void insert(int n) {
+ assert(!inHeap(n));
+ assert(ok(n));
+ indices[n] = heap.size();
+ heap.push(n);
+ percolateUp(indices[n]);
+ }
+
+
+ int getmin() {
+ //printing heap
+ if(BEEV::print_sat_varorder) {
+ // fprintf(stderr, "Vijay: heap before getmin: ");
+ // for (uint i = 1; i < (uint)heap.size(); i++)
+ // fprintf(stderr, "%d ", heap[i]);
+ // fprintf(stderr, "\n");
+ }
+
+ int r = heap[1];
+ heap[1] = heap.last();
+ indices[heap[1]] = 1;
+ indices[r] = 0;
+ heap.pop();
+ if (heap.size() > 1)
+ percolateDown(1);
+ return r;
+ }
+
+ // fool proof variant of insert/increase
+ void update (int n) {
+ //fprintf(stderr, "update heap: ");
+ //for (uint i = 1; i < (uint)heap.size(); i++)
+ // fprintf(stderr, "%d ", heap[i]);
+ //fprintf(stderr, "\n");
+ setBounds(n+1);
+ if (!inHeap(n))
+ insert(n);
+ else {
+ percolateUp(indices[n]);
+ percolateDown(indices[n]);
+ }
+ }
+
+
+ bool heapProperty() {
+ return heapProperty(1); }
+
+
+ bool heapProperty(int i) {
+ return i >= heap.size()
+ || ((parent(i) == 0 || !comp(heap[i],heap[parent(i)])) && heapProperty(left(i)) && heapProperty(right(i))); }
+
+ template <class F> void filter(const F& filt) {
+ int i,j;
+ for (i = j = 1; i < heap.size(); i++)
+ if (filt(heap[i])){
+ heap[j] = heap[i];
+ indices[heap[i]] = j++;
+ }else
+ indices[heap[i]] = 0;
+
+ heap.shrink(i - j);
+ for (int i = heap.size() / 2; i >= 1; i--)
+ percolateDown(i);
+
+ assert(heapProperty());
+ }
+
+};
+
+//=================================================================================================
+};
+#endif
Added: klee/trunk/stp/sat/LICENSE
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/LICENSE?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/LICENSE (added)
+++ klee/trunk/stp/sat/LICENSE Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Added: klee/trunk/stp/sat/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Makefile (added)
+++ klee/trunk/stp/sat/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+include ../Makefile.common
+
+SRCS = Solver.C Simplifier.C
+OBJS = $(SRCS:.C=.o)
+
+libsatsolver.a: $(OBJS)
+ $(AR) rc $@ $^
+ $(RANLIB) $@
+
+Solver.o: Solver.C Solver.h Sort.h SolverTypes.h VarOrder.h Global.h Heap.h
+Simplifier.o: Simplifier.C Solver.h Sort.h SolverTypes.h VarOrder.h Global.h Heap.h
+
+clean:
+ rm -rf *.o *~ *.a depend.mak .#*
+depend:
+ makedepend -- $(CFLAGS) -- $(SRCS)
Added: klee/trunk/stp/sat/Simplifier.C
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Simplifier.C?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Simplifier.C (added)
+++ klee/trunk/stp/sat/Simplifier.C Wed May 20 23:36:41 2009
@@ -0,0 +1,542 @@
+/************************************************************************************[Simplifier.C]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#include "Solver.h"
+
+namespace MINISAT {
+
+static const int grow = 0;
+
+//#define WEAKEN
+//#define MATING
+//#define ASSYMM
+
+bool Solver::assymmetricBranching(Clause& c)
+{
+ assert(decisionLevel() == 0);
+
+ //fprintf(stderr, "assymmetric branching on clause: "); printClause(c); fprintf(stderr, "\n");
+ if (satisfied(c)){
+ //fprintf(stderr, "subsumed.\n");
+ return true; }
+
+ int old;
+ vec<Lit> copy; for (int i = 0; i < c.size(); i++) copy.push(c[i]);
+
+ do {
+ assert(copy.size() == c.size());
+
+ old = copy.size();
+
+ //fprintf(stderr, "checking that clause is normalized\n");
+ //for (int i = 0; i < copy.size(); i++)
+ // assert(value(copy[i]) == l_Undef);
+
+ for (int i = 0; i < copy.size(); i++){
+ trail_lim.push(trail.size());
+ //fprintf(stderr, " -- trying to delete literal "); printLit(copy[i]);
+ for (int j = 0; j < copy.size(); j++)
+ if (j != i)
+ check(enqueue(~copy[j]));
+
+ if (propagate() != NULL){
+ //fprintf(stderr, " succeeded\n");
+ cancelUntil(0);
+ Lit l = copy[i];
+ assert(find(copy, l));
+ remove(copy, l);
+ if (!strengthen(c, l))
+ return false;
+ i--;
+
+ if (c.size() == 1)
+ return propagate() == NULL;
+ else
+ assert(qhead == trail.size());
+ }
+ else
+ //fprintf(stderr, " failed\n");
+
+ cancelUntil(0);
+ }
+
+ //} while (false);
+ } while (copy.size() < old);
+
+ return true;
+}
+
+// Returns FALSE if clause is always satisfied ('out_clause' should not be used).
+//bool Solver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
+bool Solver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
+{
+ stats.merges++;
+
+ bool ps_smallest = _ps.size() < _qs.size();
+ const Clause& ps = ps_smallest ? _qs : _ps;
+ const Clause& qs = ps_smallest ? _ps : _qs;
+
+ for (int i = 0; i < qs.size(); i++){
+ if (var(qs[i]) != v){
+ for (int j = 0; j < ps.size(); j++)
+ if (var(ps[j]) == var(qs[i])) {
+ if (ps[j] == ~qs[i])
+ return false;
+ else
+ goto next;
+ }
+ out_clause.push(qs[i]);
+ }
+ next:;
+ }
+
+ for (int i = 0; i < ps.size(); i++)
+ if (var(ps[i]) != v)
+ out_clause.push(ps[i]);
+
+ return true;
+}
+
+
+void Solver::gather(vec<Clause*>& clauses)
+{
+ //fprintf(stderr, "Gathering clauses for backwards subsumption\n");
+ int ntouched = 0;
+ assert(touched.size() == occurs.size());
+ clauses.clear();
+ for (int i = 0; i < touched.size(); i++)
+ if (touched[i]){
+ const vec<Clause*>& cs = getOccurs(i);
+ ntouched++;
+ for (int j = 0; j < cs.size(); j++)
+ if (cs[j]->mark() == 0){
+ clauses.push(cs[j]);
+ cs[j]->mark(2);
+ }
+ touched[i] = 0;
+ }
+
+ //fprintf(stderr, "Touched variables %d of %d yields %d clauses to check\n", ntouched, touched.size(), clauses.size());
+ for (int i = 0; i < clauses.size(); i++)
+ clauses[i]->mark(0);
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| subsumes : (_c : ClauseId) (c : Clause&) (_d : ClauseId) (d : Clause&) -> bool
+|
+| Description:
+| Checks if c subsumes d, and at the same time, if c can be used to simplify d by subsumption
+| resolution.
+|
+| Input:
+| Indices into the 'clauses' vector _c, _d, and references to the corresponding clauses c, d.
+|
+| Result:
+| lit_Error - No subsumption or simplification
+| lit_Undef - Clause c subsumes d
+| l - The literal l can be deleted from d
+|________________________________________________________________________________________________@*/
+inline Lit Solver::subsumes(const Clause& c, const Clause& d)
+{
+ stats.subsumption_checks++;
+ if (d.size() < c.size() || (c.abstraction() & ~d.abstraction()) != 0)
+ return lit_Error;
+
+ Lit ret = lit_Undef;
+
+ for (int i = 0; i < c.size(); i++) {
+ // search for c[i] or ~c[i]
+ for (int j = 0; j < d.size(); j++)
+ if (c[i] == d[j])
+ goto ok;
+ else if (ret == lit_Undef && c[i] == ~d[j]){
+ ret = c[i];
+ goto ok;
+ }
+
+ // did not find it
+ stats.subsumption_misses++;
+ return lit_Error;
+ ok:;
+ }
+
+ return ret;
+}
+
+
+// Backward subsumption + backward subsumption resolution
+bool Solver::backwardSubsumptionCheck()
+{
+ while (subsumption_queue.size() > 0 || qhead < trail.size()){
+
+ // if propagation queue is non empty, take the first literal and
+ // create a dummy unit clause
+ if (qhead < trail.size()){
+ Lit l = trail[qhead++];
+ (*bwdsub_tmpunit)[0] = l;
+ assert(bwdsub_tmpunit->mark() == 0);
+ subsumption_queue.push(bwdsub_tmpunit);
+ }
+ Clause& c = *subsumption_queue.last(); subsumption_queue.pop();
+
+ if (c.mark())
+ continue;
+
+ if (c.size() == 1 && !enqueue(c[0]))
+ return false;
+
+ // (1) find best variable to scan
+ Var best = var(c[0]);
+ for (int i = 1; i < c.size(); i++)
+ if (occurs[var(c[i])].size() < occurs[best].size())
+ best = var(c[i]);
+
+ // (2) search all candidates
+ const vec<Clause*>& cs = getOccurs(best);
+
+ for (int j = 0; j < cs.size(); j++)
+ if (cs[j] != &c){
+ if (cs[j]->mark())
+ continue;
+ if (c.mark())
+ break;
+
+ //fprintf(stderr, "backward candidate "); printClause(*cs[j]); fprintf(stderr, "\n");
+ Lit l = subsumes(c, *cs[j]);
+ if (l == lit_Undef){
+ //fprintf(stderr, "clause backwards subsumed\n");
+ //fprintf(stderr, " >> clause %d: ", cs[j]->mark()); printClause(*cs[j]); fprintf(stderr, "\n");
+ //fprintf(stderr, " >> clause %d: ", c.mark()); printClause(c); fprintf(stderr, "\n");
+ removeClause(*cs[j], false);
+ }else if (l != lit_Error){
+ //fprintf(stderr, "backwards subsumption resolution\n");
+ //fprintf(stderr, " >> clause %d: ", cs[j]->mark()); printClause(*cs[j]); fprintf(stderr, "\n");
+ //fprintf(stderr, " >> clause %d: ", c.mark()); printClause(c); fprintf(stderr, "\n");
+
+ assert(cs[j]->size() > 1);
+ assert(find(*cs[j], ~l));
+
+ subsumption_queue.push(cs[j]);
+ if (!strengthen(*cs[j], ~l))
+ return false;
+
+ // did current candidate get deleted from cs? then check candidate at index j again
+ if (var(l) == best)
+ j--;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+bool Solver::eliminateVar(Var v, bool fail)
+{
+ assert(hasVarProp(v, p_frozen));
+
+ vec<Clause*> pos, neg;
+ const vec<Clause*>& cls = getOccurs(v);
+
+ if (value(v) != l_Undef || cls.size() == 0)
+ return true;
+
+ //fprintf(stderr, "trying to eliminate var %d\n", v+1);
+ for (int i = 0; i < cls.size(); i++){
+ //fprintf(stderr, "clause: "); printClause(*cls[i]); fprintf(stderr, "\n");
+ if (find(*cls[i], Lit(v)))
+ pos.push(cls[i]);
+ else{
+ assert(find(*cls[i], ~Lit(v)));
+ neg.push(cls[i]);
+ }
+ }
+
+#ifdef WEAKEN
+ vec<int> posc(pos.size(), 0);
+ vec<int> negc(neg.size(), 0);
+#endif
+ // check if number of clauses decreases
+ int cnt = 0;
+ vec<Lit> resolvent;
+ for (int i = 0; i < pos.size(); i++)
+ for (int j = 0; j < neg.size(); j++){
+ resolvent.clear();
+ if (merge(*pos[i], *neg[j], v, resolvent)){
+ cnt++;
+#ifdef WEAKEN
+ posc[i]++;
+ negc[j]++;
+#endif
+ }
+#ifndef WEAKEN
+ if (cnt > cls.size() + grow)
+ return true;
+#else
+#ifdef MATING
+ if (cnt > cls.size() + grow)
+ if (posc[i] > 0)
+ break;
+#endif
+#endif
+ assert(pos.size() <= n_occ[toInt(Lit(v))]);
+ assert(neg.size() <= n_occ[toInt(~Lit(v))]);
+ }
+
+#ifdef WEAKEN
+#ifdef MATING
+ for (int i = 0; i < neg.size(); i++)
+ if (negc[i] == 0)
+ for (int j = 0; j < pos.size(); j++){
+ resolvent.clear();
+ if (merge(*neg[i], *pos[j], v, resolvent)){
+ negc[i]++;
+ break;
+ }
+ }
+#endif
+ for (int i = 0; i < pos.size(); i++)
+ if (posc[i] == 0)
+ removeClause(*pos[i], false);
+
+ for (int i = 0; i < neg.size(); i++)
+ if (negc[i] == 0)
+ removeClause(*neg[i], false);
+
+ if (cnt > cls.size() + grow)
+ return true;
+#endif
+ //if (pos.size() != n_occ[toInt(Lit(v))])
+ // fprintf(stderr, "pos.size() = %d, n_occ[toInt(Lit(v))] = %d\n", pos.size(), n_occ[toInt(Lit(v))]);
+ assert(pos.size() == n_occ[toInt(Lit(v))]);
+ //if (neg.size() != n_occ[toInt(~Lit(v))])
+ // fprintf(stderr, "neg.size() = %d, n_occ[toInt(Lit(v))] = %d\n", neg.size(), n_occ[toInt(Lit(v))]);
+ assert(neg.size() == n_occ[toInt(~Lit(v))]);
+ assert(cnt <= cls.size() + grow);
+ setVarProp(v, p_decisionvar, false);
+
+ // produce clauses in cross product
+ int top = clauses.size();
+ for (int i = 0; i < pos.size(); i++)
+ for (int j = 0; j < neg.size(); j++){
+ resolvent.clear();
+#ifdef WEAKEN
+ if (pos[i]->mark() == 1)
+ break;
+ if (neg[j]->mark() == 1)
+ continue;
+#endif
+
+ if (merge(*pos[i], *neg[j], v, resolvent)){
+ int i, j;
+ for (i = j = 0; i < resolvent.size(); i++)
+ if (value(resolvent[i]) == l_True)
+ goto next;
+ else if (value(resolvent[i]) == l_Undef)
+ resolvent[j++] = resolvent[i];
+ resolvent.shrink(i - j);
+
+ if (resolvent.size() == 1){
+ if (!enqueue(resolvent[0]))
+ return false;
+ }else{
+ int apa = clauses.size();
+ check(newClause(resolvent, false, true));
+ assert(apa + 1 == clauses.size());
+ }
+ }
+ next:;
+ }
+
+ if (fail){
+ fprintf(stderr, "eliminated var %d, %d <= %d\n", v+1, cnt, cls.size());
+ fprintf(stderr, "previous clauses:\n");
+ for (int i = 0; i < cls.size(); i++){
+ printClause(*cls[i]);
+ fprintf(stderr, "\n");
+ }
+
+ fprintf(stderr, "new clauses:\n");
+ for (int i = top; i < clauses.size(); i++){
+ printClause(*clauses[i]);
+ fprintf(stderr, "\n");
+ }
+
+ assert(0); }
+
+ //fprintf(stderr, "eliminated var %d, %d <= %d\n", v+1, cnt, cls.size());
+ //fprintf(stderr, "previous clauses:\n");
+ //for (int i = 0; i < cls.size(); i++){
+ // printClause(*cls[i]);
+ // fprintf(stderr, "\n");
+ //}
+ //
+ //fprintf(stderr, "new clauses:\n");
+ //for (int i = top; i < clauses.size(); i++){
+ // printClause(*clauses[i]);
+ // fprintf(stderr, "\n");
+ //}
+
+ // delete + store old clauses
+ eliminated_var.push(v);
+ eliminated_lim.push(eliminated.size());
+ for (int i = 0; i < cls.size(); i++){
+ eliminated.push(Clause_new(*cls[i]));
+
+#ifdef WEAKEN
+ if (cls[i]->mark() == 0)
+#endif
+ removeClause(*cls[i], false);
+
+ }
+
+ assert(subsumption_queue.size() == 0);
+ for (int i = top; i < clauses.size(); i++)
+#ifdef ASSYMM
+ if (clauses[i]->mark() == 0)
+ if (!assymmetricBranching(*clauses[i]))
+ return false;
+ else
+ subsumption_queue.push(clauses[i]);
+#else
+ if (clauses[i]->mark() == 0)
+ subsumption_queue.push(clauses[i]);
+#endif
+
+ return backwardSubsumptionCheck();
+}
+
+
+void Solver::extendModel()
+{
+ assert(eliminated_var.size() == eliminated_lim.size());
+ for (int i = eliminated_var.size()-1; i >= 0; i--){
+ Var v = eliminated_var[i];
+ Lit l = lit_Undef;
+
+ //fprintf(stderr, "extending var %d\n", v+1);
+
+ for (int j = eliminated_lim[i]; j < (i+1 >= eliminated_lim.size() ? eliminated.size() : eliminated_lim[i+1]); j++){
+ assert(j < eliminated.size());
+ Clause& c = *eliminated[j];
+
+ //fprintf(stderr, "checking clause: "); printClause(c); fprintf(stderr, "\n");
+
+ for (int k = 0; k < c.size(); k++)
+ if (var(c[k]) == v)
+ l = c[k];
+ else if (value(c[k]) != l_False)
+ goto next;
+
+ assert(l != lit_Undef);
+ //fprintf(stderr, "Fixing var %d to %d\n", v+1, !sign(l));
+
+ assigns[v] = toInt(lbool(!sign(l)));
+ break;
+
+ next:;
+ }
+
+ if (value(v) == l_Undef)
+ assigns[v] = toInt(l_True);
+ }
+}
+
+
+bool Solver::eliminate()
+{
+ assert(subsumption);
+
+ int cnt = 0;
+ //fprintf(stderr, "eliminating variables\n");
+
+#ifdef INVARIANTS
+ // check that all clauses are simplified
+ fprintf(stderr, "Checking that all clauses are normalized prior to variable elimination\n");
+ for (int i = 0; i < clauses.size(); i++)
+ if (clauses[i]->mark() == 0){
+ Clause& c = *clauses[i];
+ for (int j = 0; j < c.size(); j++)
+ assert(value(c[j]) == l_Undef);
+ }
+ fprintf(stderr, "done.\n");
+#endif
+
+ for (;;){
+ gather(subsumption_queue);
+
+ if (subsumption_queue.size() == 0 && heap.size() == 0)
+ break;
+
+ //fprintf(stderr, "backwards subsumption: %10d\n", subsumption_queue.size());
+ if (!backwardSubsumptionCheck())
+ return false;
+
+ //fprintf(stderr, "variable elimination: %10d\n", heap.size());
+ cnt = 0;
+ for (;;){
+ assert(!heap.empty() || heap.size() == 0);
+ if (heap.empty())
+ break;
+
+ Var elim = heap.getmin();
+
+ assert(hasVarProp(elim, p_frozen));
+
+ //for (int i = 1; i < heap.heap.size(); i++)
+ // assert(heap.comp(elim, heap.heap[i]) || !heap.comp(elim, heap.heap[i]));
+
+ //if (cnt++ % 100 == 0)
+ // fprintf(stderr, "left %10d\r", heap.size());
+
+ if (!eliminateVar(elim))
+ return false;
+ }
+ }
+#ifdef INVARIANTS
+ // check that no more subsumption is possible
+ fprintf(stderr, "Checking that no more subsumption is possible\n");
+ cnt = 0;
+ for (int i = 0; i < clauses.size(); i++){
+ if (cnt++ % 1000 == 0)
+ fprintf(stderr, "left %10d\r", clauses.size() - i);
+ for (int j = 0; j < i; j++)
+ assert(clauses[i]->mark() ||
+ clauses[j]->mark() ||
+ subsumes(*clauses[i], *clauses[j]) == lit_Error);
+ }
+ fprintf(stderr, "done.\n");
+
+ // check that no more elimination is possible
+ fprintf(stderr, "Checking that no more elimination is possible\n");
+ for (int i = 0; i < nVars(); i++){
+ if (hasVarProp(i, p_frozen))
+ eliminateVar(i, true);
+ }
+ fprintf(stderr, "done.\n");
+
+#endif
+
+ assert(qhead == trail.size());
+
+ return true;
+}
+};
Added: klee/trunk/stp/sat/Solver.C
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Solver.C?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Solver.C (added)
+++ klee/trunk/stp/sat/Solver.C Wed May 20 23:36:41 2009
@@ -0,0 +1,811 @@
+/****************************************************************************************[Solver.C]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#include "Solver.h"
+#include "Sort.h"
+#include <cmath>
+
+namespace MINISAT {
+//=================================================================================================
+// Operations on clauses:
+
+
+/*_________________________________________________________________________________________________
+|
+| newClause : (ps : const vec<Lit>&) (learnt : bool) -> [void]
+|
+| Description:
+| Allocate and add a new clause to the SAT solvers clause database.
+|
+| Input:
+| ps - The new clause as a vector of literals.
+| learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the
+| asserting literal. An appropriate 'enqueue()' operation will be performed on this
+| literal. One of the watches will always be on this literal, the other will be set to
+| the literal with the highest decision level.
+|
+| Effect:
+| Activity heuristics are updated.
+|________________________________________________________________________________________________@*/
+bool Solver::newClause(const vec<Lit>& ps_, bool learnt, bool normalized)
+{
+ vec<Lit> qs;
+ if (!learnt && !normalized){
+ assert(decisionLevel() == 0);
+ ps_.copyTo(qs); // Make a copy of the input vector.
+
+ // Remove duplicates:
+ sortUnique(qs);
+
+ // Check if clause is satisfied:
+ for (int i = 0; i < qs.size()-1; i++){
+ if (qs[i] == ~qs[i+1])
+ return true; }
+ for (int i = 0; i < qs.size(); i++){
+ if (value(qs[i]) == l_True)
+ return true; }
+
+ // Remove false literals:
+ int i, j;
+ for (i = j = 0; i < qs.size(); i++)
+ if (value(qs[i]) != l_False)
+ qs[j++] = qs[i];
+ qs.shrink(i - j);
+ }
+ const vec<Lit>& ps = learnt || normalized ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals.
+
+ if (ps.size() == 0)
+ return false;
+ else if (ps.size() == 1){
+ assert(decisionLevel() == 0);
+ return enqueue(ps[0]);
+ }else{
+ // Allocate clause:
+ Clause* c = Clause_new(ps, learnt);
+
+ if (learnt){
+ // Put the second watch on the first literal with highest decision level:
+ // (requires that this method is called at the level where the clause is asserting!)
+ int i;
+ for (i = 1; i < ps.size() && position(trailpos[var(ps[i])]) < trail_lim.last(); i++)
+ ;
+ (*c)[1] = ps[i];
+ (*c)[i] = ps[1];
+
+ // Bump, enqueue, store clause:
+ claBumpActivity(*c); // (newly learnt clauses should be considered active)
+ check(enqueue((*c)[0], c));
+ learnts.push(c);
+ stats.learnts_literals += c->size();
+ }else{
+ // Store clause:
+ clauses.push(c);
+ stats.clauses_literals += c->size();
+
+ if (subsumption){
+ c->calcAbstraction();
+ for (int i = 0; i < c->size(); i++){
+ assert(!find(occurs[var((*c)[i])], c));
+ occurs[var((*c)[i])].push(c);
+ n_occ[toInt((*c)[i])]++;
+ touched[var((*c)[i])] = 1;
+
+ if (heap.inHeap(var((*c)[i])))
+ updateHeap(var((*c)[i]));
+ }
+ }
+
+ }
+ // Watch clause:
+ watches[toInt(~(*c)[0])].push(c);
+ watches[toInt(~(*c)[1])].push(c);
+ }
+
+ return true;
+}
+
+
+// Disposes a clauses and removes it from watcher lists. NOTE!
+// Low-level; does NOT change the 'clauses' and 'learnts' vector.
+//
+void Solver::removeClause(Clause& c, bool dealloc)
+{
+ //fprintf(stderr, "delete %d: ", _c); printClause(c); fprintf(stderr, "\n");
+ assert(c.mark() == 0);
+
+ if (c.size() > 1){
+ assert(find(watches[toInt(~c[0])], &c));
+ assert(find(watches[toInt(~c[1])], &c));
+ remove(watches[toInt(~c[0])], &c);
+ remove(watches[toInt(~c[1])], &c); }
+
+ if (c.learnt()) stats.learnts_literals -= c.size();
+ else stats.clauses_literals -= c.size();
+
+ if (subsumption && !c.learnt()){
+ for (int i = 0; i < c.size(); i++){
+ if (dealloc){
+ assert(find(occurs[var(c[i])], &c));
+ remove(occurs[var(c[i])], &c);
+ }
+ n_occ[toInt(c[i])]--;
+ updateHeap(var(c[i]));
+ }
+ }
+
+ if (dealloc)
+ xfree(&c);
+ else
+ c.mark(1);
+}
+
+
+bool Solver::satisfied(Clause& c) const
+{
+ for (int i = 0; i < c.size(); i++)
+ if (value(c[i]) == l_True)
+ return true;
+ return false; }
+
+
+bool Solver::strengthen(Clause& c, Lit l)
+{
+ assert(decisionLevel() == 0);
+ assert(c.size() > 1);
+ assert(c.mark() == 0);
+
+ assert(toInt(~c[0]) < watches.size());
+ assert(toInt(~c[1]) < watches.size());
+
+ assert(find(watches[toInt(~c[0])], &c));
+ assert(find(watches[toInt(~c[1])], &c));
+ assert(find(c,l));
+
+ if (c.learnt()) stats.learnts_literals -= 1;
+ else stats.clauses_literals -= 1;
+
+ if (c[0] == l || c[1] == l){
+ assert(find(watches[toInt(~l)], &c));
+ remove(c,l);
+ remove(watches[toInt(~l)], &c);
+ if (c.size() > 1){
+ assert(!find(watches[toInt(~c[1])], &c));
+ watches[toInt(~c[1])].push(&c); }
+ else {
+ assert(find(watches[toInt(~c[0])], &c));
+ remove(watches[toInt(~c[0])], &c);
+ removeClause(c, false);
+ }
+ }
+ else
+ remove(c,l);
+
+ assert(c.size() == 1 || find(watches[toInt(~c[0])], &c));
+ assert(c.size() == 1 || find(watches[toInt(~c[1])], &c));
+
+ if (subsumption){
+ assert(find(occurs[var(l)], &c));
+ remove(occurs[var(l)], &c);
+ assert(!find(occurs[var(l)], &c));
+
+ c.calcAbstraction();
+
+ n_occ[toInt(l)]--;
+ updateHeap(var(l));
+ }
+
+ return c.size() == 1 ? enqueue(c[0]) : true;
+}
+
+
+//=================================================================================================
+// Minor methods:
+
+
+// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be
+// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
+//
+Var Solver::newVar(bool polarity, bool dvar) {
+ int index;
+ index = nVars();
+ watches .push(); // (list for positive literal)
+ watches .push(); // (list for negative literal)
+ reason .push(NULL);
+ assigns .push(toInt(l_Undef));
+ trailpos .push(TrailPos(0,0));
+ activity .push(0);
+ order .newVar(polarity,dvar);
+ seen .push(0);
+ touched .push(0);
+ if (subsumption){
+ occurs .push();
+ n_occ .push(0);
+ n_occ .push(0);
+ heap .setBounds(index+1);
+ }
+ return index; }
+
+
+// Returns FALSE if immediate conflict.
+bool Solver::assume(Lit p) {
+ trail_lim.push(trail.size());
+ return enqueue(p); }
+
+
+// Revert to the state at given level.
+void Solver::cancelUntil(int level) {
+ if (decisionLevel() > level){
+ for (int c = trail.size()-1; c >= trail_lim[level]; c--){
+ Var x = var(trail[c]);
+ assigns[x] = toInt(l_Undef);
+ reason [x] = NULL;
+ order.undo(x); }
+ qhead = trail_lim[level];
+ trail.shrink(trail.size() - trail_lim[level]);
+ trail_lim.shrink(trail_lim.size() - level);
+ }
+}
+
+
+//=================================================================================================
+// Major methods:
+
+
+/*_________________________________________________________________________________________________
+|
+| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
+|
+| Description:
+| Analyze conflict and produce a reason clause.
+|
+| Pre-conditions:
+| * 'out_learnt' is assumed to be cleared.
+| * Current decision level must be greater than root level.
+|
+| Post-conditions:
+| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
+|
+| Effect:
+| Will undo part of the trail, upto but not beyond the assumption of the current decision level.
+|________________________________________________________________________________________________@*/
+void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel)
+{
+ int pathC = 0;
+ int btpos = -1;
+ Lit p = lit_Undef;
+
+ // Generate conflict clause:
+ //
+ out_learnt.push(); // (leave room for the asserting literal)
+ int index = trail.size()-1;
+ do{
+ assert(confl != NULL); // (otherwise should be UIP)
+ Clause& c = *confl;
+
+ if (c.learnt())
+ claBumpActivity(c);
+
+ for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
+ Lit q = c[j];
+ if (!seen[var(q)] && position(trailpos[var(q)]) >= trail_lim[0]){
+ varBumpActivity(q);
+ seen[var(q)] = 1;
+ if (position(trailpos[var(q)]) >= trail_lim.last())
+ pathC++;
+ else{
+ out_learnt.push(q);
+ btpos = max(btpos, position(trailpos[var(q)]));
+ }
+ }
+ }
+
+ // Select next clause to look at:
+ while (!seen[var(trail[index--])]);
+ p = trail[index+1];
+ confl = reason[var(p)];
+ seen[var(p)] = 0;
+ pathC--;
+
+ }while (pathC > 0);
+ out_learnt[0] = ~p;
+
+ // Find correct backtrack level
+ for (out_btlevel = trail_lim.size()-1; out_btlevel > 0 && trail_lim[out_btlevel-1] > btpos; out_btlevel--)
+ ;
+
+ int i, j;
+ if (expensive_ccmin){
+ // Simplify conflict clause (a lot):
+ //
+ uint min_level = 0;
+ for (i = 1; i < out_learnt.size(); i++)
+ min_level |= abstractLevel(trailpos[var(out_learnt[i])]); // (maintain an abstraction of levels involved in conflict)
+
+ out_learnt.copyTo(analyze_toclear);
+ for (i = j = 1; i < out_learnt.size(); i++)
+ if (reason[var(out_learnt[i])] == NULL || !analyze_removable(out_learnt[i], min_level))
+ out_learnt[j++] = out_learnt[i];
+ }else{
+ // Simplify conflict clause (a little):
+ //
+ out_learnt.copyTo(analyze_toclear);
+ for (i = j = 1; i < out_learnt.size(); i++){
+ Clause& c = *reason[var(out_learnt[i])];
+ for (int k = 1; k < c.size(); k++)
+ if (!seen[var(c[k])] && position(trailpos[var(c[k])]) >= trail_lim[0]){
+ out_learnt[j++] = out_learnt[i];
+ break; }
+ }
+ }
+
+ stats.max_literals += out_learnt.size();
+ out_learnt.shrink(i - j);
+ stats.tot_literals += out_learnt.size();
+
+ for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared)
+}
+
+
+// Check if 'p' can be removed. 'min_level' is used to abort early if visiting literals at a level that cannot be removed.
+//
+bool Solver::analyze_removable(Lit p, uint min_level)
+{
+ analyze_stack.clear(); analyze_stack.push(p);
+ int top = analyze_toclear.size();
+ while (analyze_stack.size() > 0){
+ assert(reason[var(analyze_stack.last())] != NULL);
+ Clause& c = *reason[var(analyze_stack.last())]; analyze_stack.pop();
+
+ for (int i = 1; i < c.size(); i++){
+ Lit p = c[i];
+ TrailPos tp = trailpos[var(p)];
+ if (!seen[var(p)] && position(tp) >= trail_lim[0]){
+ if (reason[var(p)] != NULL && (abstractLevel(tp) & min_level) != 0){
+ seen[var(p)] = 1;
+ analyze_stack.push(p);
+ analyze_toclear.push(p);
+ }else{
+ for (int j = top; j < analyze_toclear.size(); j++)
+ seen[var(analyze_toclear[j])] = 0;
+ analyze_toclear.shrink(analyze_toclear.size() - top);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| analyzeFinal : (p : Lit) -> [void]
+|
+| Description:
+| Specialized analysis procedure to express the final conflict in terms of assumptions.
+| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
+| stores the result in 'out_conflict'.
+|________________________________________________________________________________________________@*/
+void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
+{
+ out_conflict.clear();
+ out_conflict.push(p);
+
+ if (decisionLevel() == 0)
+ return;
+
+ seen[var(p)] = 1;
+
+ int start = position(trailpos[var(p)]);
+ for (int i = start; i >= trail_lim[0]; i--){
+ Var x = var(trail[i]);
+ if (seen[x]){
+ if (reason[x] == NULL){
+ assert(position(trailpos[x]) >= trail_lim[0]);
+ out_conflict.push(~trail[i]);
+ }else{
+ Clause& c = *reason[x];
+ for (int j = 1; j < c.size(); j++)
+ if (position(trailpos[var(c[j])]) >= trail_lim[0])
+ seen[var(c[j])] = 1;
+ }
+ seen[x] = 0;
+ }
+ }
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| enqueue : (p : Lit) (from : Clause*) -> [bool]
+|
+| Description:
+| Puts a new fact on the propagation queue as well as immediately updating the variable's value.
+| Should a conflict arise, FALSE is returned.
+|
+| Input:
+| p - The fact to enqueue
+| from - [Optional] Fact propagated from this (currently) unit clause. Stored in 'reason[]'.
+| Default value is NULL (no reason).
+|
+| Output:
+| TRUE if fact was enqueued without conflict, FALSE otherwise.
+|________________________________________________________________________________________________@*/
+bool Solver::enqueue(Lit p, Clause* from)
+{
+
+ if (value(p) != l_Undef)
+ return value(p) != l_False;
+ else{
+ assigns [var(p)] = toInt(lbool(!sign(p)));
+ trailpos[var(p)] = TrailPos(trail.size(),decisionLevel());
+ reason [var(p)] = from;
+ trail.push(p);
+ return true;
+ }
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| propagate : [void] -> [Clause*]
+|
+| Description:
+| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
+| otherwise NULL.
+|
+| Post-conditions:
+| * the propagation queue is empty, even if there was a conflict.
+|________________________________________________________________________________________________@*/
+Clause* Solver::propagate()
+{
+ if (decisionLevel() == 0 && subsumption)
+ return backwardSubsumptionCheck() ? NULL : propagate_tmpempty;
+
+ Clause* confl = NULL;
+ //fprintf(stderr, "propagate, qhead = %d, qtail = %d\n", qhead, qtail);
+ while (qhead < trail.size()){
+ stats.propagations++;
+ simpDB_props--;
+
+ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate.
+ vec<Clause*>& ws = watches[toInt(p)];
+ Clause **i, **j, **end;
+
+ for (i = j = (Clause**)ws, end = i + ws.size(); i != end;){
+ Clause& c = **i++;
+
+ // Make sure the false literal is data[1]:
+ Lit false_lit = ~p;
+ if (c[0] == false_lit)
+ c[0] = c[1], c[1] = false_lit;
+
+ assert(c[1] == false_lit);
+
+ // If 0th watch is true, then clause is already satisfied.
+ Lit first = c[0];
+ if (value(first) == l_True){
+ *j++ = &c;
+ }else{
+ // Look for new watch:
+ for (int k = 2; k < c.size(); k++)
+ if (value(c[k]) != l_False){
+ c[1] = c[k]; c[k] = false_lit;
+ watches[toInt(~c[1])].push(&c);
+ goto FoundWatch; }
+
+ // Did not find watch -- clause is unit under assignment:
+ *j++ = &c;
+ if (!enqueue(first, &c)){
+ confl = &c;
+ qhead = trail.size();
+ // Copy the remaining watches:
+ while (i < end)
+ *j++ = *i++;
+ }
+ FoundWatch:;
+ }
+ }
+ ws.shrink(i - j);
+ }
+
+ return confl;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| reduceDB : () -> [void]
+|
+| Description:
+| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
+| clauses are clauses that are reason to some assignment. Binary clauses are never removed.
+|________________________________________________________________________________________________@*/
+struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } };
+void Solver::reduceDB()
+{
+ int i, j;
+ double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity
+
+ sort(learnts, reduceDB_lt());
+ for (i = j = 0; i < learnts.size() / 2; i++){
+ if (learnts[i]->size() > 2 && !locked(*learnts[i]))
+ removeClause(*learnts[i]);
+ else
+ learnts[j++] = learnts[i];
+ }
+ for (; i < learnts.size(); i++){
+ if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() < extra_lim)
+ removeClause(*learnts[i]);
+ else
+ learnts[j++] = learnts[i];
+ }
+ learnts.shrink(i - j);
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| simplifyDB : [void] -> [bool]
+|
+| Description:
+| Simplify the clause database according to the current top-level assigment. Currently, the only
+| thing done here is the removal of satisfied clauses, but more things can be put here.
+|________________________________________________________________________________________________@*/
+bool Solver::simplifyDB(bool expensive)
+{
+ assert(decisionLevel() == 0);
+ if (!ok || propagate() != NULL)
+ return ok = false;
+
+ if (nAssigns() == simpDB_assigns ||
+ (!subsumption && simpDB_props > 0)) // (nothing has changed or preformed a simplification too recently)
+ return true;
+
+ if (subsumption){
+ if (expensive && !eliminate())
+ return ok = false;
+
+ // Move this cleanup code to its own method ?
+ int i , j;
+ vec<Var> dirty;
+ for (i = 0; i < clauses.size(); i++)
+ if (clauses[i]->mark() == 1){
+ Clause& c = *clauses[i];
+ for (int k = 0; k < c.size(); k++)
+ if (!seen[var(c[k])]){
+ seen[var(c[k])] = 1;
+ dirty.push(var(c[k]));
+ }
+ }
+
+ for (i = 0; i < dirty.size(); i++){
+ cleanOcc(dirty[i]);
+ seen[dirty[i]] = 0;
+ }
+
+ for (i = j = 0; i < clauses.size(); i++)
+ if (clauses[i]->mark() == 1)
+ xfree(clauses[i]);
+ else
+ clauses[j++] = clauses[i];
+ clauses.shrink(i - j);
+ }
+
+ // Remove satisfied clauses:
+ for (int type = 0; type < (subsumption ? 1 : 2); type++){ // (only scan learnt clauses if subsumption is on)
+ vec<Clause*>& cs = type ? learnts : clauses;
+ int j = 0;
+ for (int i = 0; i < cs.size(); i++){
+ assert(cs[i]->mark() == 0);
+ if (satisfied(*cs[i]))
+ removeClause(*cs[i]);
+ else
+ cs[j++] = cs[i];
+ }
+ cs.shrink(cs.size()-j);
+ }
+ order.cleanup();
+
+ simpDB_assigns = nAssigns();
+ simpDB_props = stats.clauses_literals + stats.learnts_literals; // (shouldn't depend on 'stats' really, but it will do for now)
+
+ return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool]
+|
+| Description:
+| Search for a model the specified number of conflicts, keeping the number of learnt clauses
+| below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to
+| indicate infinity.
+|
+| Output:
+| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
+| all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
+| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
+|________________________________________________________________________________________________@*/
+lbool Solver::search(int nof_conflicts, int nof_learnts)
+{
+ assert(ok);
+ int backtrack_level;
+ int conflictC = 0;
+ vec<Lit> learnt_clause;
+
+ stats.starts++;
+ var_decay = 1 / params.var_decay;
+ cla_decay = 1 / params.clause_decay;
+
+ for (;;){
+ Clause* confl = propagate();
+ if (confl != NULL){
+ // CONFLICT
+ stats.conflicts++; conflictC++;
+ if (decisionLevel() == 0) return l_False;
+
+ learnt_clause.clear();
+ analyze(confl, learnt_clause, backtrack_level);
+ cancelUntil(backtrack_level);
+ newClause(learnt_clause, true);
+ varDecayActivity();
+ claDecayActivity();
+
+ }else{
+ // NO CONFLICT
+
+ if (nof_conflicts >= 0 && conflictC >= nof_conflicts){
+ // Reached bound on number of conflicts:
+ progress_estimate = progressEstimate();
+ cancelUntil(0);
+ return l_Undef; }
+
+ // Simplify the set of problem clauses:
+ if (decisionLevel() == 0 && !simplifyDB())
+ return l_False;
+
+ if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts)
+ // Reduce the set of learnt clauses:
+ reduceDB();
+
+ Lit next = lit_Undef;
+
+ if (decisionLevel() < assumptions.size()){
+ // Perform user provided assumption:
+ next = assumptions[decisionLevel()];
+ if (value(next) == l_False){
+ analyzeFinal(~next, conflict);
+ return l_False; }
+ }else{
+ // New variable decision:
+ stats.decisions++;
+ next = order.select(params.random_var_freq, decisionLevel());
+ }
+ if (next == lit_Undef)
+ // Model found:
+ return l_True;
+
+ check(assume(next));
+ }
+ }
+}
+
+
+// Return search-space coverage. Not extremely reliable.
+//
+double Solver::progressEstimate()
+{
+ double progress = 0;
+ double F = 1.0 / nVars();
+
+ for (int i = 0; i <= decisionLevel(); i++){
+ int beg = i == 0 ? 0 : trail_lim[i - 1];
+ int end = i == decisionLevel() ? trail.size() : trail_lim[i];
+ progress += pow(F, i) * (end - beg);
+ }
+
+ return progress / nVars();
+}
+
+
+// Divide all variable activities by 1e100.
+//
+void Solver::varRescaleActivity()
+{
+ for (int i = 0; i < nVars(); i++)
+ activity[i] *= 1e-100;
+ var_inc *= 1e-100;
+}
+
+
+// Divide all constraint activities by 1e100.
+//
+void Solver::claRescaleActivity()
+{
+ for (int i = 0; i < learnts.size(); i++)
+ learnts[i]->activity() *= 1e-20;
+ cla_inc *= 1e-20;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+| solve : (assumps : const vec<Lit>&) -> [bool]
+|
+| Description:
+| Top-level solve.
+|________________________________________________________________________________________________@*/
+bool Solver::solve(const vec<Lit>& assumps)
+{
+ model.clear();
+ conflict.clear();
+
+ if (!simplifyDB(true)) return false;
+
+
+ double nof_conflicts = params.restart_first;
+ double nof_learnts = nClauses() * params.learntsize_factor;
+ lbool status = l_Undef;
+ assumps.copyTo(assumptions);
+
+ if (verbosity >= 1){
+ reportf("==================================[MINISAT]====================================\n");
+ reportf("| Conflicts | ORIGINAL | LEARNT | Progress |\n");
+ reportf("| | Vars Clauses Literals | Limit Clauses Lit/Cl | |\n");
+ reportf("===============================================================================\n");
+ }
+
+ // Search:
+ while (status == l_Undef){
+ if (verbosity >= 1)
+ //reportf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (int)stats.learnts_literals, (double)stats.learnts_literals/nLearnts(), progress_estimate*100);
+ reportf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", (int)stats.conflicts, order.size(), nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (double)stats.learnts_literals/nLearnts(), progress_estimate*100);
+ status = search((int)nof_conflicts, (int)nof_learnts);
+ nof_conflicts *= params.restart_inc;
+ nof_learnts *= params.learntsize_inc;
+ }
+
+ if (verbosity >= 1)
+ reportf("==============================================================================\n");
+
+ if (status == l_True){
+ // Copy model:
+ extendModel();
+#if 1
+ //fprintf(stderr, "Verifying model.\n");
+ for (int i = 0; i < clauses.size(); i++)
+ assert(satisfied(*clauses[i]));
+ for (int i = 0; i < eliminated.size(); i++)
+ assert(satisfied(*eliminated[i]));
+#endif
+ model.growTo(nVars());
+ for (int i = 0; i < nVars(); i++) model[i] = value(i);
+ }else{
+ assert(status == l_False);
+ if (conflict.size() == 0)
+ ok = false;
+ }
+
+ cancelUntil(0);
+ return status == l_True;
+}
+};//end of MINISAT namespace
Added: klee/trunk/stp/sat/Solver.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Solver.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Solver.h (added)
+++ klee/trunk/stp/sat/Solver.h Wed May 20 23:36:41 2009
@@ -0,0 +1,359 @@
+/****************************************************************************************[Solver.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Solver_h
+#define Solver_h
+
+#include "SolverTypes.h"
+#include "VarOrder.h"
+
+namespace MINISAT {
+// Redfine if you want output to go somewhere else:
+#define reportf(format, args...) ( printf(format , ## args), fflush(stdout) )
+
+
+//=================================================================================================
+// Solver -- the main class:
+struct SolverStats {
+ int64 starts, decisions, propagations, conflicts;
+ int64 clauses_literals, learnts_literals, max_literals, tot_literals;
+ int64 subsumption_checks, subsumption_misses, merges;
+ SolverStats() :
+ starts(0), decisions(0), propagations(0), conflicts(0)
+ , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0)
+ , subsumption_checks(0), subsumption_misses(0), merges(0)
+ { }
+};
+
+
+struct SearchParams {
+ double var_decay, clause_decay, random_var_freq;
+ double restart_inc, learntsize_inc, learntsize_factor;
+ int restart_first;
+
+ SearchParams(double v = 0.95, double c = 0.999, double r = 0.02,
+ double ri = 1.5, double li = 1.1, double lf = (double)1/(double)3,
+ int rf = 100) :
+ var_decay(v), clause_decay(c), random_var_freq(r),
+ restart_inc(ri), learntsize_inc(li), learntsize_factor(lf),
+ restart_first(rf) { }
+};
+
+ struct ElimLt {
+ const vec<int>& n_occ;
+
+ ElimLt(const vec<int>& no) : n_occ(no) {}
+ int cost (Var x) const { return n_occ[toInt(Lit(x))] * n_occ[toInt(~Lit(x))]; }
+ bool operator()(Var x, Var y) const { return cost(x) < cost(y); }
+ };
+
+class Solver {
+protected:
+ // Solver state:
+ bool ok; // If FALSE,the constraints are already unsatisfiable.
+ // No part of solver state may be used!
+ vec<Clause*> clauses; // List of problem clauses.
+ vec<Clause*> learnts; // List of learnt clauses.
+ int n_bin_clauses; // Keep track of number of binary clauses "inlined" into the watcher lists (we do this primarily to get identical behavior to the version without the binary clauses trick).
+ double cla_inc; // Amount to bump next clause with.
+ double cla_decay; // INVERSE decay factor for clause activity: stores 1/decay.
+
+ vec<double> activity; // A heuristic measurement of the activity of a variable.
+ double var_inc; // Amount to bump next variable with.
+ double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order.
+ VarOrder order; // Keeps track of the decision variable order.
+ vec<char> properties; // TODO: describe!!!
+
+ vec<vec<Clause*> > watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
+ vec<char> assigns; // The current assignments (lbool:s stored as char:s).
+ vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made.
+ vec<int> trail_lim; // Separator indices for different decision levels in 'trail'.
+ vec<Clause*> reason; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
+ vec<TrailPos> trailpos; // 'trailpos[var]' contains the position in the trail at wich the assigment was made.
+ int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
+ int simpDB_assigns; // Number of top-level assignments since last execution of 'simplifyDB()'.
+ int64 simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplifyDB()'.
+ vec<Lit> assumptions; // Current set of assumptions provided to solve by the user.
+
+ bool subsumption;
+ vec<char> touched;
+ vec<vec<Clause*> > occurs;
+ vec<int> n_occ;
+ Heap<ElimLt> heap;
+ vec<Clause*> subsumption_queue;
+
+ vec<Clause*> eliminated;
+ vec<int> eliminated_lim;
+ vec<Var> eliminated_var;
+
+ // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
+ // used, exept 'seen' wich is used in several places.
+ //
+ vec<char> seen;
+ vec<Lit> analyze_stack;
+ vec<Lit> analyze_toclear;
+ Clause* propagate_tmpempty;
+ Clause* propagate_tmpbin;
+ Clause* analyze_tmpbin;
+ Clause* bwdsub_tmpunit;
+
+ vec<Lit> addBinary_tmp;
+ vec<Lit> addTernary_tmp;
+
+ // Main internal methods:
+ //
+ bool assume (Lit p);
+ void cancelUntil (int level);
+ void record (const vec<Lit>& clause);
+
+ void analyze (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel); // (bt = backtrack)
+ bool analyze_removable(Lit p, uint min_level); // (helper method for 'analyze()')
+ void analyzeFinal (Lit p, vec<Lit>& out_conflict);
+ bool enqueue (Lit fact, Clause* from = NULL);
+ Clause* propagate ();
+ void reduceDB ();
+ Lit pickBranchLit ();
+ lbool search (int nof_conflicts, int nof_learnts);
+ double progressEstimate ();
+
+ // Variable properties:
+ void setVarProp (Var v, uint prop, bool b) { order.setVarProp(v, prop, b); }
+ bool hasVarProp (Var v, uint prop) const { return order.hasVarProp(v, prop); }
+ void updateHeap (Var v) {
+ if (hasVarProp(v, p_frozen))
+ heap.update(v); }
+
+ // Simplification methods:
+ //
+ void cleanOcc (Var v) {
+ assert(subsumption);
+ vec<Clause*>& occ = occurs[v];
+ int i, j;
+ for (i = j = 0; i < occ.size(); i++)
+ if (occ[i]->mark() != 1)
+ occ[j++] = occ[i];
+ occ.shrink(i - j);
+ }
+
+ vec<Clause*>& getOccurs (Var x) { cleanOcc(x); return occurs[x]; }
+ void gather (vec<Clause*>& clauses);
+ Lit subsumes (const Clause& c, const Clause& d);
+ bool assymmetricBranching (Clause& c);
+ bool merge (const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause);
+
+ bool backwardSubsumptionCheck ();
+ bool eliminateVar (Var v, bool fail = false);
+ bool eliminate ();
+ void extendModel ();
+
+ // Activity:
+ //
+ void varBumpActivity(Lit p) {
+ if (var_decay < 0) return; // (negative decay means static variable order -- don't bump)
+ if ( (activity[var(p)] += var_inc) > 1e100 ) varRescaleActivity();
+ order.update(var(p)); }
+ void varDecayActivity () { if (var_decay >= 0) var_inc *= var_decay; }
+ void varRescaleActivity();
+ void claDecayActivity () { cla_inc *= cla_decay; }
+ void claRescaleActivity();
+
+ // Operations on clauses:
+ //
+ bool newClause(const vec<Lit>& ps, bool learnt = false, bool normalized = false);
+ void claBumpActivity (Clause& c) { if ( (c.activity() += cla_inc) > 1e20 ) claRescaleActivity(); }
+ bool locked (const Clause& c) const { return reason[var(c[0])] == &c; }
+ bool satisfied (Clause& c) const;
+ bool strengthen (Clause& c, Lit l);
+ void removeClause (Clause& c, bool dealloc = true);
+
+ int decisionLevel() const { return trail_lim.size(); }
+
+public:
+ Solver() : ok (true)
+ , n_bin_clauses (0)
+ , cla_inc (1)
+ , cla_decay (1)
+ , var_inc (1)
+ , var_decay (1)
+ , order (assigns, activity)
+ , qhead (0)
+ , simpDB_assigns (-1)
+ , simpDB_props (0)
+ , subsumption (true)
+ , heap (n_occ)
+ , params ()
+ , expensive_ccmin (true)
+ , verbosity (0)
+ , progress_estimate(0)
+ {
+ vec<Lit> dummy(2,lit_Undef);
+ propagate_tmpbin = Clause_new(dummy);
+ analyze_tmpbin = Clause_new(dummy);
+ dummy.pop();
+ bwdsub_tmpunit = Clause_new(dummy);
+ dummy.pop();
+ propagate_tmpempty = Clause_new(dummy);
+ addBinary_tmp .growTo(2);
+ addTernary_tmp.growTo(3);
+ }
+
+ ~Solver() {
+ xfree(propagate_tmpbin);
+ xfree(analyze_tmpbin);
+ xfree(bwdsub_tmpunit);
+ xfree(propagate_tmpempty);
+ for (int i = 0; i < eliminated.size(); i++) xfree(eliminated[i]);
+ for (int i = 0; i < learnts.size(); i++) xfree(learnts[i]);
+ for (int i = 0; i < clauses.size(); i++) xfree(clauses[i]); }
+
+ // Helpers: (semi-internal)
+ //
+ lbool value(Var x) const { return toLbool(assigns[x]); }
+ lbool value(Lit p) const { return sign(p) ? ~toLbool(assigns[var(p)]) : toLbool(assigns[var(p)]); }
+
+ int nAssigns() { return trail.size(); }
+ int nClauses() { return clauses.size(); }
+ int nLearnts() { return learnts.size(); }
+ int nConflicts() { return (int)stats.conflicts; }
+
+ // Statistics: (read-only member variable)
+ //
+ SolverStats stats;
+
+ // Mode of operation:
+ //
+ SearchParams params; // Restart frequency etc.
+ bool expensive_ccmin; // Controls conflict clause minimization. TRUE by default.
+ int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything
+
+ // Problem specification:
+ //
+ Var newVar (bool polarity = true, bool dvar = true);
+ int nVars () { return assigns.size(); }
+ bool addUnit (Lit p) { return ok && (ok = enqueue(p)); }
+ bool addBinary (Lit p, Lit q) { addBinary_tmp [0] = p; addBinary_tmp [1] = q; return addClause(addBinary_tmp); }
+ bool addTernary(Lit p, Lit q, Lit r) { addTernary_tmp[0] = p; addTernary_tmp[1] = q; addTernary_tmp[2] = r; return addClause(addTernary_tmp); }
+ bool addClause (const vec<Lit>& ps) { if (ok && !newClause(ps)) ok = false; return ok; }
+
+ // Variable mode:
+ //
+ void freezeVar (Var v) { setVarProp(v, p_frozen, true); updateHeap(v); }
+
+ // Solving:
+ //
+ bool okay () { return ok; } // FALSE means solver is in a conflicting state
+ bool simplifyDB (bool expensive = true);
+ bool solve (const vec<Lit>& assumps);
+ bool solve () { vec<Lit> tmp; return solve(tmp); }
+ void turnOffSubsumption() {
+ subsumption = false;
+ occurs.clear(true);
+ n_occ.clear(true);
+ }
+
+ double progress_estimate; // Set by 'search()'.
+ vec<lbool> model; // If problem is satisfiable, this vector contains the model (if any).
+ vec<Lit> conflict; // If problem is unsatisfiable (possibly under assumptions), this vector represent the conflict clause expressed in the assumptions.
+
+ double returnActivity(int i) { return activity[i];}
+ void updateInitialActivity(int i, double act) {activity[i] = act; order.heap.update(i);}
+};
+
+
+//=================================================================================================
+// Debug:
+
+
+#define L_LIT "%sx%d"
+#define L_lit(p) sign(p)?"~":"", var(p)
+
+// Just like 'assert()' but expression will be evaluated in the release version as well.
+inline void check(bool expr) { assert(expr); }
+
+static void printLit(Lit l)
+{
+ fprintf(stderr, "%s%d", sign(l) ? "-" : "", var(l)+1);
+}
+
+template<class C>
+static void printClause(const C& c)
+{
+ for (int i = 0; i < c.size(); i++){
+ printLit(c[i]);
+ fprintf(stderr, " ");
+ }
+}
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#ifdef _MSC_VER
+
+#include <ctime>
+
+static inline double cpuTime(void) {
+ return (double)clock() / CLOCKS_PER_SEC; }
+
+static inline int64 memUsed() {
+ return 0; }
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#else
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static inline double cpuTime(void) {
+ struct rusage ru;
+ getrusage(RUSAGE_SELF, &ru);
+ return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
+
+#if defined(__linux__) || defined(__CYGWIN__)
+static inline int memReadStat(int field)
+{
+ char name[256];
+ pid_t pid = getpid();
+ sprintf(name, "/proc/%d/statm", pid);
+ FILE* in = fopen(name, "rb");
+ if (in == NULL) return 0;
+ int value;
+ for (; field >= 0; field--) {
+ int res = fscanf(in, "%d", &value);
+ (void) res;
+ }
+ fclose(in);
+ return value;
+}
+
+static inline int64 memUsed() { return (int64)memReadStat(0) * (int64)getpagesize(); }
+#else
+// use this by default. Mac OS X (Darwin) does not define an os type
+//defined(__FreeBSD__)
+
+static inline int64 memUsed(void) {
+ struct rusage ru;
+ getrusage(RUSAGE_SELF, &ru);
+ return ru.ru_maxrss*1024; }
+
+#endif
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#endif
+
+//=================================================================================================
+};
+#endif
Added: klee/trunk/stp/sat/SolverTypes.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/SolverTypes.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/SolverTypes.h (added)
+++ klee/trunk/stp/sat/SolverTypes.h Wed May 20 23:36:41 2009
@@ -0,0 +1,127 @@
+/***********************************************************************************[SolverTypes.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+
+#ifndef SolverTypes_h
+#define SolverTypes_h
+
+#include "Global.h"
+
+namespace MINISAT {
+
+//=================================================================================================
+// Variables, literals, clause IDs:
+
+
+// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
+// so that they can be used as array indices.
+
+typedef int Var;
+#define var_Undef (-1)
+
+
+struct Lit {
+ int x;
+
+ Lit() : x(2*var_Undef) { } // (lit_Undef)
+ explicit Lit(Var var, bool sign = false) : x((var+var) + (int)sign) { }
+};
+
+// Don't use these for constructing/deconstructing literals. Use the normal constructors instead.
+inline int toInt (Lit p) { return p.x; } // A "toInt" method that guarantees small, positive integers suitable for array indexing.
+inline Lit toLit (int i) { Lit p; p.x = i; return p; } // Inverse of 'toInt()'
+
+inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; }
+inline bool sign (Lit p) { return p.x & 1; }
+inline int var (Lit p) { return p.x >> 1; }
+inline Lit unsign (Lit p) { Lit q; q.x = p.x & ~1; return q; }
+inline Lit id (Lit p, bool sgn) { Lit q; q.x = p.x ^ (int)sgn; return q; }
+
+inline bool operator == (Lit p, Lit q) { return toInt(p) == toInt(q); }
+inline bool operator != (Lit p, Lit q) { return toInt(p) != toInt(q); }
+inline bool operator < (Lit p, Lit q) { return toInt(p) < toInt(q); } // '<' guarantees that p, ~p are adjacent in the ordering.
+
+
+const Lit lit_Undef(var_Undef, false); // }- Useful special constants.
+const Lit lit_Error(var_Undef, true ); // }
+
+
+//=================================================================================================
+// Clause -- a simple class for representing a clause:
+
+class Clause {
+ uint size_etc;
+ union { float act; uint abst; } apa;
+ Lit data[0];
+public:
+ // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
+ template<class V>
+ Clause(const V& ps, bool learnt) {
+ size_etc = (ps.size() << 3) | (uint)learnt;
+ for (int i = 0; i < ps.size(); i++) data[i] = ps[i];
+ if (learnt) apa.act = 0; else apa.abst = 0; }
+
+ // -- use this function instead:
+ template<class V>
+ friend Clause* Clause_new(const V& ps, bool learnt = false) {
+ assert(sizeof(Lit) == sizeof(uint));
+ assert(sizeof(float) == sizeof(uint));
+ void* mem = xmalloc<char>(sizeof(Clause) + sizeof(uint)*(ps.size()));
+ return new (mem) Clause(ps, learnt); }
+
+ int size () const { return size_etc >> 3; }
+ void shrink (int i) { assert(i <= size()); size_etc = (((size_etc >> 3) - i) << 3) | (size_etc & 7); }
+ void pop () { shrink(1); }
+ bool learnt () const { return size_etc & 1; }
+ uint mark () const { return (size_etc >> 1) & 3; }
+ void mark (uint m) { size_etc = (size_etc & ~6) | ((m & 3) << 1); }
+ Lit operator [] (int i) const { return data[i]; }
+ Lit& operator [] (int i) { return data[i]; }
+
+ float& activity () { return apa.act; }
+
+ uint abstraction () const { return apa.abst; }
+
+ void calcAbstraction() {
+ uint abstraction = 0;
+ for (int i = 0; i < size(); i++)
+ abstraction |= 1 << (var(data[i]) & 31);
+ apa.abst = abstraction; }
+};
+
+
+//=================================================================================================
+// TrailPos -- Stores an index into the trail as well as an approximation of a level. This data
+// is recorded for each assigment. (Replaces the old level information)
+
+
+class TrailPos {
+ int tp;
+ public:
+ explicit TrailPos(int index, int level) : tp( (index << 5) + (level & 31) ) { }
+
+ friend int abstractLevel(const TrailPos& p) { return 1 << (p.tp & 31); }
+ friend int position (const TrailPos& p) { return p.tp >> 5; }
+
+ bool operator == (TrailPos other) const { return tp == other.tp; }
+ bool operator < (TrailPos other) const { return tp < other.tp; }
+};
+
+};
+#endif
Added: klee/trunk/stp/sat/Sort.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/Sort.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/Sort.h (added)
+++ klee/trunk/stp/sat/Sort.h Wed May 20 23:36:41 2009
@@ -0,0 +1,133 @@
+/******************************************************************************************[Sort.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Sort_h
+#define Sort_h
+
+
+namespace MINISAT {
+//=================================================================================================
+
+
+template<class T>
+struct LessThan_default {
+ bool operator () (T x, T y) { return x < y; }
+};
+
+
+//=================================================================================================
+
+
+template <class T, class LessThan>
+void selectionSort(T* array, int size, LessThan lt)
+{
+ int i, j, best_i;
+ T tmp;
+
+ for (i = 0; i < size-1; i++){
+ best_i = i;
+ for (j = i+1; j < size; j++){
+ if (lt(array[j], array[best_i]))
+ best_i = j;
+ }
+ tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+ }
+}
+template <class T> static inline void selectionSort(T* array, int size) {
+ selectionSort(array, size, LessThan_default<T>()); }
+
+
+template <class T, class LessThan>
+void sort(T* array, int size, LessThan lt, double& seed)
+{
+ if (size <= 15)
+ selectionSort(array, size, lt);
+
+ else{
+ T pivot = array[irand(seed, size)];
+ T tmp;
+ int i = -1;
+ int j = size;
+
+ for(;;){
+ do i++; while(lt(array[i], pivot));
+ do j--; while(lt(pivot, array[j]));
+
+ if (i >= j) break;
+
+ tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+ }
+
+ sort(array , i , lt, seed);
+ sort(&array[i], size-i, lt, seed);
+ }
+}
+template <class T, class LessThan> void sort(T* array, int size, LessThan lt) {
+ double seed = 91648253; sort(array, size, lt, seed); }
+template <class T> static inline void sort(T* array, int size) {
+ sort(array, size, LessThan_default<T>()); }
+
+
+template <class T, class LessThan>
+void sortUnique(T* array, int& size, LessThan lt)
+{
+ int i, j;
+ T last;
+
+ if (size == 0) return;
+
+ sort(array, size, lt);
+
+ i = 1;
+ last = array[0];
+ for (j = 1; j < size; j++){
+ if (lt(last, array[j])){
+ last = array[i] = array[j];
+ i++; }
+ }
+
+ size = i;
+}
+template <class T> static inline void sortUnique(T* array, int& size) {
+ sortUnique(array, size, LessThan_default<T>()); }
+
+
+//=================================================================================================
+// For 'vec's:
+
+
+template <class T, class LessThan> void sort(vec<T>& v, LessThan lt) {
+ sort((T*)v, v.size(), lt); }
+template <class T> void sort(vec<T>& v) {
+ sort(v, LessThan_default<T>()); }
+
+
+template <class T, class LessThan> void sortUnique(vec<T>& v, LessThan lt) {
+ int size = v.size();
+ T* data = v.release();
+ sortUnique(data, size, lt);
+ v.~vec<T>();
+ new (&v) vec<T>(data, size); }
+template <class T> void sortUnique(vec<T>& v) {
+ sortUnique(v, LessThan_default<T>()); }
+
+
+//=================================================================================================
+};
+#endif
Added: klee/trunk/stp/sat/VarOrder.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/sat/VarOrder.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/sat/VarOrder.h (added)
+++ klee/trunk/stp/sat/VarOrder.h Wed May 20 23:36:41 2009
@@ -0,0 +1,146 @@
+/**************************************************************************************[VarOrder.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef VarOrder_h
+#define VarOrder_h
+
+#include "SolverTypes.h"
+#include "Solver.h"
+#include "Heap.h"
+#include "../AST/ASTUtil.h"
+
+namespace MINISAT {
+ //=================================================================================================
+
+ struct VarOrder_lt {
+ const vec<double>& activity;
+ bool operator () (Var x, Var y) { return activity[x] > activity[y]; }
+ VarOrder_lt(const vec<double>& act) : activity(act) { }
+ };
+
+
+ enum { p_decisionvar = 0, p_polarity = 1, p_frozen = 2, p_dontcare = 3 };
+
+
+ class VarOrder {
+ const vec<char>& assigns; // var->val. Pointer to external assignment table.
+ const vec<double>& activity; // var->act. Pointer to external activity table.
+ vec<char> properties;
+ //Heap<VarOrder_lt> heap;
+ //double random_seed; // For the internal random number generator
+
+ friend class VarFilter;
+ public:
+ //FIXME: Vijay: delete after experiments
+ Heap<VarOrder_lt> heap;
+ double random_seed; // For the internal random number generator
+ //FIXME ENDS HERE
+
+ VarOrder(const vec<char>& ass, const vec<double>& act) :
+ assigns(ass), activity(act), heap(VarOrder_lt(act)), random_seed(2007)
+ //assigns(ass), activity(act), heap(VarOrder_lt(act))
+ { }
+
+ int size () { return heap.size(); }
+ void setVarProp (Var v, uint prop, bool b) { properties[v] = (properties[v] & ~(1 << prop)) | (b << prop); }
+ bool hasVarProp (Var v, uint prop) const { return properties[v] & (1 << prop); }
+ inline void cleanup ();
+
+ inline void newVar(bool polarity, bool dvar);
+ inline void update(Var x); // Called when variable increased in activity.
+ inline void undo(Var x); // Called when variable is unassigned and may be selected again.
+ //Selects a new, unassigned variable (or 'var_Undef' if none exists).
+ inline Lit select(double random_freq =.0, int decision_level = 0);
+ };
+
+
+ struct VarFilter {
+ const VarOrder& o;
+ VarFilter(const VarOrder& _o) : o(_o) {}
+ bool operator()(Var v) const { return toLbool(o.assigns[v]) == l_Undef && o.hasVarProp(v, p_decisionvar); }
+ //bool operator()(Var v) const { return toLbool(o.assigns[v]) == l_Undef; }
+ };
+
+ void VarOrder::cleanup()
+ {
+ VarFilter f(*this);
+ heap.filter(f);
+ }
+
+ void VarOrder::newVar(bool polarity, bool dvar)
+ {
+ Var v = assigns.size()-1;
+ heap.setBounds(v+1);
+ properties.push(0);
+ setVarProp(v, p_decisionvar, dvar);
+ setVarProp(v, p_polarity, polarity);
+ undo(v);
+ }
+
+
+ void VarOrder::update(Var x)
+ {
+ if (heap.inHeap(x))
+ heap.increase(x);
+ }
+
+
+ void VarOrder::undo(Var x)
+ {
+ if (!heap.inHeap(x) && hasVarProp(x, p_decisionvar))
+ heap.insert(x);
+ }
+
+
+ Lit VarOrder::select(double random_var_freq, int decision_level)
+ {
+ Var next = var_Undef;
+
+ if (drand(random_seed) < random_var_freq && !heap.empty())
+ next = irand(random_seed,assigns.size());
+
+ // Activity based decision:
+ while (next == var_Undef || toLbool(assigns[next]) != l_Undef || !hasVarProp(next, p_decisionvar))
+ if (heap.empty()){
+ next = var_Undef;
+ break;
+ }else
+ next = heap.getmin();
+
+ //printing
+ if(BEEV::print_sat_varorder) {
+ if (next != var_Undef) {
+ BEEV::Convert_MINISATVar_To_ASTNode_Print(next,
+ decision_level,
+ hasVarProp(next, p_polarity));
+ // fprintf(stderr,"var = %d, prop = %d, decision = %d, polarity = %d, frozen = %d\n",
+ // next+1, properties[next], hasVarProp(next, p_decisionvar),
+ // hasVarProp(next, p_polarity), hasVarProp(next, p_frozen));
+ }
+ else
+ fprintf(stderr, "var = undef\n");
+ }
+
+ return next == var_Undef ? lit_Undef : Lit(next, hasVarProp(next, p_polarity));
+ }
+
+
+ //=================================================================================================
+};
+#endif
Added: klee/trunk/stp/simplifier/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/simplifier/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/simplifier/Makefile (added)
+++ klee/trunk/stp/simplifier/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+include ../Makefile.common
+
+SRCS = simplifier.cpp bvsolver.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libsimplifier.a: $(OBJS)
+ $(AR) rc $@ $^
+ $(RANLIB) $@
+
+clean:
+ rm -rf *.o *~ *.a .#*
Added: klee/trunk/stp/simplifier/bvsolver.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/simplifier/bvsolver.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/simplifier/bvsolver.cpp (added)
+++ klee/trunk/stp/simplifier/bvsolver.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,714 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+#include "bvsolver.h"
+
+ //This file contains the implementation of member functions of
+ //bvsolver class, which represents the bitvector arithmetic linear
+ //solver. Please also refer the STP's CAV 2007 paper for the
+ //complete description of the linear solver algorithm
+ //
+ //The bitvector solver is a partial solver, i.e. it does not solve
+ //for all variables in the system of equations. it is
+ //best-effort. it relies on the SAT solver to be complete.
+ //
+ //The BVSolver assumes that the input equations are normalized, and
+ //have liketerms combined etc.
+ //
+ //0. Traverse top-down over the input DAG, looking for a conjunction
+ //0. of equations. if you find one, then for each equation in the
+ //0. conjunction, do the following steps.
+ //
+ //1. check for Linearity of the input equation
+ //
+ //2. Solve for a "chosen" variable. The variable should occur
+ //2. exactly once and must have an odd coeff. Refer STP's CAV 2007
+ //2. paper for actual solving procedure
+ //
+ //4. Outside the solver, Substitute and Re-normalize the input DAG
+namespace BEEV {
+ //check the solver map for 'key'. If key is present, then return the
+ //value by reference in the argument 'output'
+ bool BVSolver::CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output) {
+ ASTNodeMap::iterator it;
+ if((it = FormulasAlreadySolvedMap.find(key)) != FormulasAlreadySolvedMap.end()) {
+ output = it->second;
+ return true;
+ }
+ return false;
+ } //CheckAlreadySolvedMap()
+
+ void BVSolver::UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value) {
+ FormulasAlreadySolvedMap[key] = value;
+ } //end of UpdateAlreadySolvedMap()
+
+ //FIXME This is doing way more arithmetic than it needs to.
+ //accepts an even number "in", and splits it into an odd number and
+ //a power of 2. i.e " in = b.(2^k) ". returns the odd number, and
+ //the power of two by reference
+ ASTNode BVSolver::SplitEven_into_Oddnum_PowerOf2(const ASTNode& in,
+ unsigned int& number_shifts) {
+ if(BVCONST != in.GetKind() || _bm->BVConstIsOdd(in)) {
+ FatalError("BVSolver:SplitNum_Odd_PowerOf2: input must be a BVCONST and even\n",in);
+ }
+
+ unsigned int len = in.GetValueWidth();
+ ASTNode zero = _bm->CreateZeroConst(len);
+ ASTNode two = _bm->CreateTwoConst(len);
+ ASTNode div_by_2 = in;
+ ASTNode mod_by_2 =
+ _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD,len,div_by_2,two));
+ while(mod_by_2 == zero) {
+ div_by_2 =
+ _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,div_by_2,two));
+ number_shifts++;
+ mod_by_2 =
+ _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD,len,div_by_2,two));
+ }
+ return div_by_2;
+ } //end of SplitEven_into_Oddnum_PowerOf2()
+
+ //Checks if there are any ARRAYREADS in the term, after the
+ //alreadyseenmap is cleared, i.e. traversing a new term altogether
+ bool BVSolver::CheckForArrayReads_TopLevel(const ASTNode& term) {
+ TermsAlreadySeenMap.clear();
+ return CheckForArrayReads(term);
+ }
+
+ //Checks if there are any ARRAYREADS in the term
+ bool BVSolver::CheckForArrayReads(const ASTNode& term) {
+ ASTNode a = term;
+ ASTNodeMap::iterator it;
+ if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
+ //if the term has been seen, then simply return true, else
+ //return false
+ if(ASTTrue == (it->second)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ switch(term.GetKind()) {
+ case READ:
+ //an array read has been seen. Make an entry in the map and
+ //return true
+ TermsAlreadySeenMap[term] = ASTTrue;
+ return true;
+ default: {
+ ASTVec c = term.GetChildren();
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ if(CheckForArrayReads(*it)) {
+ return true;
+ }
+ }
+ break;
+ }
+ }
+
+ //If control is here, then it means that no arrayread was seen for
+ //the input 'term'. Make an entry in the map with the term as key
+ //and FALSE as value.
+ TermsAlreadySeenMap[term] = ASTFalse;
+ return false;
+ } //end of CheckForArrayReads()
+
+ //check the solver map for 'key'. If key is present, then return the
+ //value by reference in the argument 'output'
+ bool BeevMgr::CheckSolverMap(const ASTNode& key, ASTNode& output) {
+ ASTNodeMap::iterator it;
+ if((it = SolverMap.find(key)) != SolverMap.end()) {
+ output = it->second;
+ return true;
+ }
+ return false;
+ } //end of CheckSolverMap()
+
+ bool BeevMgr::CheckSolverMap(const ASTNode& key) {
+ if(SolverMap.find(key) != SolverMap.end())
+ return true;
+ else
+ return false;
+ } //end of CheckSolverMap()
+
+ //update solvermap with (key,value) pair
+ bool BeevMgr::UpdateSolverMap(const ASTNode& key, const ASTNode& value) {
+ ASTNode var = (BVEXTRACT == key.GetKind()) ? key[0] : key;
+ if(!CheckSolverMap(var) && key != value) {
+ SolverMap[key] = value;
+ return true;
+ }
+ return false;
+ } //end of UpdateSolverMap()
+
+ //collects the vars in the term 'lhs' into the multiset Vars
+ void BVSolver::VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& Vars) {
+ TermsAlreadySeenMap.clear();
+ VarsInTheTerm(lhs,Vars);
+ }
+
+ //collects the vars in the term 'lhs' into the multiset Vars
+ void BVSolver::VarsInTheTerm(const ASTNode& term, ASTNodeMultiSet& Vars) {
+ ASTNode a = term;
+ ASTNodeMap::iterator it;
+ if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
+ //if the term has been seen, then simply return
+ return;
+ }
+
+ switch(term.GetKind()) {
+ case BVCONST:
+ return;
+ case SYMBOL:
+ //cerr << "debugging: symbol added: " << term << endl;
+ Vars.insert(term);
+ break;
+ case READ:
+ //skip the arrayname, provided the arrayname is a SYMBOL
+ if(SYMBOL == term[0].GetKind()) {
+ VarsInTheTerm(term[1],Vars);
+ }
+ else {
+ VarsInTheTerm(term[0],Vars);
+ VarsInTheTerm(term[1],Vars);
+ }
+ break;
+ default: {
+ ASTVec c = term.GetChildren();
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ VarsInTheTerm(*it,Vars);
+ }
+ break;
+ }
+ }
+
+ //ensures that you don't double count. if you have seen the term
+ //once, then memoize
+ TermsAlreadySeenMap[term] = ASTTrue;
+ return;
+ } //end of VarsInTheTerm()
+
+ bool BVSolver::DoNotSolveThis(const ASTNode& var) {
+ if(DoNotSolve_TheseVars.find(var) != DoNotSolve_TheseVars.end()) {
+ return true;
+ }
+ return false;
+ }
+
+ //chooses a variable in the lhs and returns the chosen variable
+ ASTNode BVSolver::ChooseMonom(const ASTNode& eq, ASTNode& modifiedlhs) {
+ if(!(EQ == eq.GetKind() && BVPLUS == eq[0].GetKind())) {
+ FatalError("ChooseMonom: input must be a EQ",eq);
+ }
+
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(32);
+
+ //collect all the vars in the lhs and rhs
+ ASTNodeMultiSet Vars;
+ VarsInTheTerm_TopLevel(lhs,Vars);
+
+ //handle BVPLUS case
+ ASTVec c = lhs.GetChildren();
+ ASTVec o;
+ ASTNode outmonom = _bm->CreateNode(UNDEFINED);
+ bool chosen_symbol = false;
+ bool chosen_odd = false;
+
+ //choose variables with no coeffs
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode monom = *it;
+ if(SYMBOL == monom.GetKind() &&
+ Vars.count(monom) == 1 &&
+ !_bm->VarSeenInTerm(monom,rhs) &&
+ !DoNotSolveThis(monom) &&
+ !chosen_symbol) {
+ outmonom = monom;
+ chosen_symbol = true;
+ }
+ else if(BVUMINUS == monom.GetKind() &&
+ SYMBOL == monom[0].GetKind() &&
+ Vars.count(monom[0]) == 1 &&
+ !DoNotSolveThis(monom[0]) &&
+ !_bm->VarSeenInTerm(monom[0],rhs) &&
+ !chosen_symbol) {
+ //cerr << "Chosen Monom: " << monom << endl;
+ outmonom = monom;
+ chosen_symbol = true;
+ }
+ else {
+ o.push_back(monom);
+ }
+ }
+
+ //try to choose only odd coeffed variables first
+ if(!chosen_symbol) {
+ o.clear();
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode monom = *it;
+ ASTNode var = (BVMULT == monom.GetKind()) ? monom[1] : _bm->CreateNode(UNDEFINED);
+
+ if(BVMULT == monom.GetKind() &&
+ BVCONST == monom[0].GetKind() &&
+ _bm->BVConstIsOdd(monom[0]) &&
+ ((SYMBOL == var.GetKind() &&
+ Vars.count(var) == 1)
+ ||
+ (BVEXTRACT == var.GetKind() &&
+ SYMBOL == var[0].GetKind() &&
+ BVCONST == var[1].GetKind() &&
+ zero == var[2] &&
+ !_bm->VarSeenInTerm(var[0],rhs) &&
+ !DoNotSolveThis(var[0]))
+ ) &&
+ !DoNotSolveThis(var) &&
+ !_bm->VarSeenInTerm(var,rhs) &&
+ !chosen_odd) {
+ //monom[0] is odd.
+ outmonom = monom;
+ chosen_odd = true;
+ }
+ else {
+ o.push_back(monom);
+ }
+ }
+ }
+
+ modifiedlhs = (o.size() > 1) ? _bm->CreateTerm(BVPLUS,lhs.GetValueWidth(),o) : o[0];
+ return outmonom;
+ } //end of choosemonom()
+
+ //solver function which solves for variables with odd coefficient
+ ASTNode BVSolver::BVSolve_Odd(const ASTNode& input) {
+ ASTNode eq = input;
+ //cerr << "Input to BVSolve_Odd()" << eq << endl;
+ if(!(wordlevel_solve && EQ == eq.GetKind())) {
+ return input;
+ }
+
+ ASTNode output = input;
+ if(CheckAlreadySolvedMap(input,output)) {
+ return output;
+ }
+
+ //get the lhs and the rhs, and case-split on the lhs kind
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ if(BVPLUS == lhs.GetKind()) {
+ ASTNode chosen_monom = _bm->CreateNode(UNDEFINED);
+ ASTNode leftover_lhs;
+
+ //choose monom makes sure that it gets only those vars that
+ //occur exactly once in lhs and rhs put together
+ chosen_monom = ChooseMonom(eq, leftover_lhs);
+ if(chosen_monom == _bm->CreateNode(UNDEFINED)) {
+ //no monomial was chosen
+ return eq;
+ }
+
+ //if control is here then it means that a monom was chosen
+ //
+ //construct: rhs - (lhs without the chosen monom)
+ unsigned int len = lhs.GetValueWidth();
+ leftover_lhs = _bm->SimplifyTerm_TopLevel(_bm->CreateTerm(BVUMINUS,len,leftover_lhs));
+ ASTNode newrhs = _bm->SimplifyTerm(_bm->CreateTerm(BVPLUS,len,rhs,leftover_lhs));
+ lhs = chosen_monom;
+ rhs = newrhs;
+ } //end of if(BVPLUS ...)
+
+ if(BVUMINUS == lhs.GetKind()) {
+ //equation is of the form (-lhs0) = rhs
+ ASTNode lhs0 = lhs[0];
+ rhs = _bm->SimplifyTerm(_bm->CreateTerm(BVUMINUS,rhs.GetValueWidth(),rhs));
+ lhs = lhs0;
+ }
+
+ switch(lhs.GetKind()) {
+ case SYMBOL: {
+ //input is of the form x = rhs first make sure that the lhs
+ //symbol does not occur on the rhs or that it has not been
+ //solved for
+ if(_bm->VarSeenInTerm(lhs,rhs)) {
+ //found the lhs in the rhs. Abort!
+ DoNotSolve_TheseVars.insert(lhs);
+ return eq;
+ }
+
+ //rhs should not have arrayreads in it. it complicates matters
+ //during transformation
+ // if(CheckForArrayReads_TopLevel(rhs)) {
+ // return eq;
+ // }
+
+ DoNotSolve_TheseVars.insert(lhs);
+ if(!_bm->UpdateSolverMap(lhs,rhs)) {
+ return eq;
+ }
+
+ output = ASTTrue;
+ break;
+ }
+ case BVEXTRACT: {
+ ASTNode zero = _bm->CreateZeroConst(32);
+
+ if(!(SYMBOL == lhs[0].GetKind() &&
+ BVCONST == lhs[1].GetKind() &&
+ zero == lhs[2] &&
+ !_bm->VarSeenInTerm(lhs[0],rhs) &&
+ !DoNotSolveThis(lhs[0]))) {
+ return eq;
+ }
+
+ if(_bm->VarSeenInTerm(lhs[0],rhs)) {
+ DoNotSolve_TheseVars.insert(lhs[0]);
+ return eq;
+ }
+
+ DoNotSolve_TheseVars.insert(lhs[0]);
+ if(!_bm->UpdateSolverMap(lhs,rhs)) {
+ return eq;
+ }
+
+ //if the extract of x[i:0] = t is entered into the solvermap,
+ //then also add another entry for x = x1 at t
+ ASTNode var = lhs[0];
+ ASTNode newvar = NewVar(var.GetValueWidth() - lhs.GetValueWidth());
+ newvar = _bm->CreateTerm(BVCONCAT,var.GetValueWidth(),newvar,rhs);
+ _bm->UpdateSolverMap(var,newvar);
+ output = ASTTrue;
+ break;
+ }
+ case BVMULT: {
+ //the input is of the form a*x = t. If 'a' is odd, then compute
+ //its multiplicative inverse a^-1, multiply 't' with it, and
+ //update the solver map
+ if(BVCONST != lhs[0].GetKind()) {
+ return eq;
+ }
+
+ if(!(SYMBOL == lhs[1].GetKind() ||
+ (BVEXTRACT == lhs[1].GetKind() &&
+ SYMBOL == lhs[1][0].GetKind()))) {
+ return eq;
+ }
+
+ bool ChosenVar_Is_Extract = (BVEXTRACT == lhs[1].GetKind()) ? true : false;
+
+ //if coeff is even, then we know that all the coeffs in the eqn
+ //are even. Simply return the eqn
+ if(!_bm->BVConstIsOdd(lhs[0])) {
+ return eq;
+ }
+
+ ASTNode a = _bm->MultiplicativeInverse(lhs[0]);
+ ASTNode chosenvar = (BVEXTRACT == lhs[1].GetKind()) ? lhs[1][0] : lhs[1];
+ ASTNode chosenvar_value =
+ _bm->SimplifyTerm(_bm->CreateTerm(BVMULT,rhs.GetValueWidth(),a,rhs));
+
+ //if chosenvar is seen in chosenvar_value then abort
+ if(_bm->VarSeenInTerm(chosenvar,chosenvar_value)) {
+ //abort solving
+ DoNotSolve_TheseVars.insert(lhs);
+ return eq;
+ }
+
+ //rhs should not have arrayreads in it. it complicates matters
+ //during transformation
+ // if(CheckForArrayReads_TopLevel(chosenvar_value)) {
+ // return eq;
+ // }
+
+ //found a variable to solve
+ DoNotSolve_TheseVars.insert(chosenvar);
+ chosenvar = lhs[1];
+ if(!_bm->UpdateSolverMap(chosenvar,chosenvar_value)) {
+ return eq;
+ }
+
+ if(ChosenVar_Is_Extract) {
+ ASTNode var = lhs[1][0];
+ ASTNode newvar = NewVar(var.GetValueWidth() - lhs[1].GetValueWidth());
+ newvar = _bm->CreateTerm(BVCONCAT,var.GetValueWidth(),newvar,chosenvar_value);
+ _bm->UpdateSolverMap(var,newvar);
+ }
+ output = ASTTrue;
+ break;
+ }
+ default:
+ output = eq;
+ break;
+ }
+
+ UpdateAlreadySolvedMap(input,output);
+ return output;
+ } //end of BVSolve_Odd()
+
+ //Create a new variable of ValueWidth 'n'
+ ASTNode BVSolver::NewVar(unsigned int n) {
+ std:: string c("v");
+ char d[32];
+ sprintf(d,"%d",_symbol_count++);
+ std::string ccc(d);
+ c += "_solver_" + ccc;
+
+ ASTNode CurrentSymbol = _bm->CreateSymbol(c.c_str());
+ CurrentSymbol.SetValueWidth(n);
+ CurrentSymbol.SetIndexWidth(0);
+ return CurrentSymbol;
+ } //end of NewVar()
+
+ //The toplevel bvsolver(). Checks if the formula has already been
+ //solved. If not, the solver() is invoked. If yes, then simply drop
+ //the formula
+ ASTNode BVSolver::TopLevelBVSolve(const ASTNode& input) {
+ if(!wordlevel_solve) {
+ return input;
+ }
+
+ Kind k = input.GetKind();
+ if(!(EQ == k || AND == k)) {
+ return input;
+ }
+
+ ASTNode output = input;
+ if(CheckAlreadySolvedMap(input,output)) {
+ //output is TRUE. The formula is thus dropped
+ return output;
+ }
+ ASTVec o;
+ ASTVec c;
+ if(EQ == k)
+ c.push_back(input);
+ else
+ c = input.GetChildren();
+ ASTVec eveneqns;
+ ASTNode solved = ASTFalse;
+ for(ASTVec::iterator it = c.begin(), itend = c.end();it != itend;it++) {
+ //_bm->ASTNodeStats("Printing before calling simplifyformula inside the solver:", *it);
+ ASTNode aaa = (ASTTrue == solved && EQ == it->GetKind()) ? _bm->SimplifyFormula(*it,false) : *it;
+ //ASTNode aaa = *it;
+ //_bm->ASTNodeStats("Printing after calling simplifyformula inside the solver:", aaa);
+ aaa = BVSolve_Odd(aaa);
+ //_bm->ASTNodeStats("Printing after oddsolver:", aaa);
+ bool even = false;
+ aaa = CheckEvenEqn(aaa, even);
+ if(even) {
+ eveneqns.push_back(aaa);
+ }
+ else {
+ if(ASTTrue != aaa) {
+ o.push_back(aaa);
+ }
+ }
+ solved = aaa;
+ }
+
+ ASTNode evens;
+ if(eveneqns.size() > 0) {
+ //if there is a system of even equations then solve them
+ evens = (eveneqns.size() > 1) ? _bm->CreateNode(AND,eveneqns) : eveneqns[0];
+ //evens = _bm->SimplifyFormula(evens,false);
+ evens = BVSolve_Even(evens);
+ _bm->ASTNodeStats("Printing after evensolver:", evens);
+ }
+ else {
+ evens = ASTTrue;
+ }
+ output = (o.size() > 0) ? ((o.size() > 1) ? _bm->CreateNode(AND,o) : o[0]) : ASTTrue;
+ output = _bm->CreateNode(AND,output,evens);
+
+ UpdateAlreadySolvedMap(input,output);
+ return output;
+ } //end of TopLevelBVSolve()
+
+ ASTNode BVSolver::CheckEvenEqn(const ASTNode& input, bool& evenflag) {
+ ASTNode eq = input;
+ //cerr << "Input to BVSolve_Odd()" << eq << endl;
+ if(!(wordlevel_solve && EQ == eq.GetKind())) {
+ evenflag = false;
+ return eq;
+ }
+
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+ //lhs must be a BVPLUS, and rhs must be a BVCONST
+ if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
+ evenflag = false;
+ return eq;
+ }
+
+ ASTVec lhs_c = lhs.GetChildren();
+ ASTNode savetheconst = rhs;
+ for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
+ ASTNode aaa = *it;
+ Kind itk = aaa.GetKind();
+
+ if(BVCONST == itk){
+ //check later if the constant is even or not
+ savetheconst = aaa;
+ continue;
+ }
+
+ if(!(BVMULT == itk &&
+ BVCONST == aaa[0].GetKind() &&
+ SYMBOL == aaa[1].GetKind() &&
+ !_bm->BVConstIsOdd(aaa[0]))) {
+ //If the monomials of the lhs are NOT of the form 'a*x' where
+ //'a' is even, then return the false
+ evenflag = false;
+ return eq;
+ }
+ }//end of for loop
+
+ //if control is here then it means that all coeffs are even. the
+ //only remaining thing is to check if the constant is even or not
+ if(_bm->BVConstIsOdd(savetheconst)) {
+ //the constant turned out to be odd. we have UNSAT eqn
+ evenflag = false;
+ return ASTFalse;
+ }
+
+ //all is clear. the eqn in even, through and through
+ evenflag = true;
+ return eq;
+ } //end of CheckEvenEqn
+
+ //solve an eqn whose monomials have only even coefficients
+ ASTNode BVSolver::BVSolve_Even(const ASTNode& input) {
+ if(!wordlevel_solve) {
+ return input;
+ }
+
+ if(!(EQ == input.GetKind() || AND == input.GetKind())) {
+ return input;
+ }
+
+ ASTNode output;
+ if(CheckAlreadySolvedMap(input,output)) {
+ return output;
+ }
+
+ ASTVec input_c;
+ if(EQ == input.GetKind()) {
+ input_c.push_back(input);
+ }
+ else {
+ input_c = input.GetChildren();
+ }
+
+ //power_of_2 holds the exponent of 2 in the coeff
+ unsigned int power_of_2 = 0;
+ //we need this additional variable to find the lowest power of 2
+ unsigned int power_of_2_lowest = 0xffffffff;
+ //the monom which has the least power of 2 in the coeff
+ ASTNode monom_with_best_coeff;
+ for(ASTVec::iterator jt=input_c.begin(),jtend=input_c.end();jt!=jtend;jt++) {
+ ASTNode eq = *jt;
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+ //lhs must be a BVPLUS, and rhs must be a BVCONST
+ if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
+ return input;
+ }
+
+ ASTVec lhs_c = lhs.GetChildren();
+ ASTNode odd;
+ for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
+ ASTNode aaa = *it;
+ Kind itk = aaa.GetKind();
+ if(!(BVCONST == itk &&
+ !_bm->BVConstIsOdd(aaa)) &&
+ !(BVMULT == itk &&
+ BVCONST == aaa[0].GetKind() &&
+ SYMBOL == aaa[1].GetKind() &&
+ !_bm->BVConstIsOdd(aaa[0]))) {
+ //If the monomials of the lhs are NOT of the form 'a*x' or 'a'
+ //where 'a' is even, then return the eqn
+ return input;
+ }
+
+ //we are gauranteed that if control is here then the monomial is
+ //of the form 'a*x' or 'a', where 'a' is even
+ ASTNode coeff = (BVCONST == itk) ? aaa : aaa[0];
+ odd = SplitEven_into_Oddnum_PowerOf2(coeff,power_of_2);
+ if(power_of_2 < power_of_2_lowest) {
+ power_of_2_lowest = power_of_2;
+ monom_with_best_coeff = aaa;
+ }
+ power_of_2 = 0;
+ }//end of inner for loop
+ } //end of outer for loop
+
+ //get the exponent
+ power_of_2 = power_of_2_lowest;
+
+ //if control is here, we are gauranteed that we have chosen a
+ //monomial with fewest powers of 2
+ ASTVec formula_out;
+ for(ASTVec::iterator jt=input_c.begin(),jtend=input_c.end();jt!=jtend;jt++) {
+ ASTNode eq = *jt;
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+ //lhs must be a BVPLUS, and rhs must be a BVCONST
+ if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
+ return input;
+ }
+
+ unsigned len = lhs.GetValueWidth();
+ ASTNode hi = _bm->CreateBVConst(32,len-1);
+ ASTNode low = _bm->CreateBVConst(32,len - power_of_2);
+ ASTNode low_minus_one = _bm->CreateBVConst(32,len - power_of_2 - 1);
+ ASTNode low_zero = _bm->CreateZeroConst(32);
+ unsigned newlen = len - power_of_2;
+ ASTNode two_const = _bm->CreateTwoConst(len);
+
+ unsigned count = power_of_2;
+ ASTNode two = two_const;
+ while(--count) {
+ two = _bm->BVConstEvaluator(_bm->CreateTerm(BVMULT,len,two_const,two));
+ }
+ ASTVec lhs_c = lhs.GetChildren();
+ ASTVec lhs_out;
+ for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
+ ASTNode aaa = *it;
+ Kind itk = aaa.GetKind();
+ if(BVCONST == itk) {
+ aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,aaa,two));
+ aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT,newlen,aaa,low_minus_one,low_zero));
+ }
+ else {
+ //it must be of the form a*x
+ ASTNode coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,aaa[0],two));
+ coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT,newlen,coeff,low_minus_one,low_zero));
+ ASTNode upper_x, lower_x;
+ //upper_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, power_of_2, aaa[1], hi, low));
+ lower_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, newlen,aaa[1],low_minus_one,low_zero));
+ aaa = _bm->CreateTerm(BVMULT,newlen,coeff,lower_x);
+ }
+ lhs_out.push_back(aaa);
+ }//end of inner forloop()
+ rhs = _bm->CreateZeroConst(newlen);
+ lhs = _bm->CreateTerm(BVPLUS,newlen,lhs_out);
+ formula_out.push_back(_bm->CreateSimplifiedEQ(lhs,rhs));
+ } //end of outer forloop()
+
+ output =
+ (formula_out.size() > 0) ? (formula_out.size() > 1) ? _bm->CreateNode(AND,formula_out) : formula_out[0] : ASTTrue;
+
+ UpdateAlreadySolvedMap(input,output);
+ return output;
+ } //end of BVSolve_Even()
+};//end of namespace BEEV
Added: klee/trunk/stp/simplifier/bvsolver.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/simplifier/bvsolver.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/simplifier/bvsolver.h (added)
+++ klee/trunk/stp/simplifier/bvsolver.h Wed May 20 23:36:41 2009
@@ -0,0 +1,134 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+namespace BEEV {
+
+ //This class represents the bitvector arithmetic linear solver.
+ //
+ //The bitvector solver is a partial solver, i.e. it does not solve
+ //for all variables in the system of equations. it is
+ //best-effort. it relies on the SAT solver to be complete.
+ //
+ //The BVSolver assumes that the input equations are normalized, and
+ //have liketerms combined etc.
+ //
+ //0. Traverse top-down over the input DAG, looking for a conjunction
+ //0. of equations. if you find one, then for each equation in the
+ //0. conjunction, do the following steps.
+ //
+ //1. check for Linearity of the input equation
+ //
+ //2. Solve for a "chosen" variable. The variable should occur
+ //2. exactly once and must have an odd coeff. Refer STP's CAV 2007
+ //2. paper for actual solving procedure
+ //
+ //4. Outside the solver, Substitute and Re-normalize the input DAG
+ class BVSolver {
+ //Ptr to toplevel manager that manages bit-vector expressions
+ //(i.e. construct various kinds of expressions), and also has
+ //member functions that simplify bit-vector expressions
+ BeevMgr * _bm;
+ ASTNode ASTTrue, ASTFalse;
+
+ //Those formulas which have already been solved. If the same
+ //formula occurs twice then do not solve the second occurence, and
+ //instead drop it
+ ASTNodeMap FormulasAlreadySolvedMap;
+
+ //this map is useful while traversing terms and uniquely
+ //identifying variables in the those terms. Prevents double
+ //counting.
+ ASTNodeMap TermsAlreadySeenMap;
+ ASTNodeMap TermsAlreadySeenMap_ForArrays;
+
+ //count is used in the creation of new variables
+ unsigned int _symbol_count;
+
+ //solved variables list: If a variable has been solved for then do
+ //not solve for it again
+ ASTNodeSet DoNotSolve_TheseVars;
+
+ //checks if var has been solved for or not. if yes, then return
+ //true else return false
+ bool DoNotSolveThis(const ASTNode& var);
+
+ //traverses a term, and creates a multiset of all variables in the
+ //term. Does memoization to avoid double counting.
+ void VarsInTheTerm(const ASTNode& lhs, ASTNodeMultiSet& v);
+ void VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& v);
+
+ //choose a suitable var from the term
+ ASTNode ChooseMonom(const ASTNode& eq, ASTNode& modifiedterm);
+ //accepts an equation and solves for a variable or a monom in it
+ ASTNode BVSolve_Odd(const ASTNode& eq);
+
+ //solves equations of the form a*x=t where 'a' is even. Has a
+ //return value, unlike the normal BVSolve()
+ ASTNode BVSolve_Even(const ASTNode& eq);
+ ASTNode CheckEvenEqn(const ASTNode& input, bool& evenflag);
+
+ //Checks for arrayreads in a term. if yes then returns true, else
+ //return false
+ bool CheckForArrayReads(const ASTNode& term);
+ bool CheckForArrayReads_TopLevel(const ASTNode& term);
+
+ //Creates new variables used in solving
+ ASTNode NewVar(unsigned int n);
+
+ //this function return true if the var occurs in term, else the
+ //function returns false
+ bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
+
+ //takes an even number "in" as input, and returns an odd number
+ //(return value) and a power of 2 (as number_shifts by reference),
+ //such that in = (odd_number * power_of_2).
+ //
+ //Refer STP's CAV 2007 (or Clark Barrett's 1998 paper on
+ //bit-vector arithmetic published in DAC 1998) paper for precise
+ //understanding of the algorithm
+ ASTNode SplitEven_into_Oddnum_PowerOf2(const ASTNode& in, unsigned int& number_shifts);
+
+ //Once a formula has been solved, then update the alreadysolvedmap
+ //with the formula, and the solved value. The solved value can be
+ //described using the following example: Suppose input to the
+ //solver is
+ //
+ // input key: x = 2 AND y = x + t
+ //
+ // output value: y = 2 + t
+ void UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value);
+
+ //This function checks if the key (formula) has already been
+ //solved for.
+ //
+ //If yes it returns TRUE and fills the "output" with the
+ //solved-value (call by reference argument),
+ //
+ //else returns FALSE
+ bool CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output);
+ public:
+ //constructor
+ BVSolver(BeevMgr * bm) : _bm(bm), _symbol_count(0) {
+ ASTTrue = _bm->CreateNode(TRUE);
+ ASTFalse = _bm->CreateNode(FALSE);
+ };
+
+ //Destructor
+ ~BVSolver() {
+ TermsAlreadySeenMap.clear();
+ DoNotSolve_TheseVars.clear();
+ }
+
+ //Top Level Solver: Goes over the input DAG, identifies the
+ //equation to be solved, solves them,
+ ASTNode TopLevelBVSolve(const ASTNode& a);
+ }; //end of class bvsolver
+};//end of namespace BEEV
Added: klee/trunk/stp/simplifier/simplifier.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/stp/simplifier/simplifier.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/stp/simplifier/simplifier.cpp (added)
+++ klee/trunk/stp/simplifier/simplifier.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,2495 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+namespace BEEV {
+
+ bool BeevMgr::CheckSimplifyMap(const ASTNode& key,
+ ASTNode& output, bool pushNeg) {
+ ASTNodeMap::iterator it, itend;
+ it = pushNeg ? SimplifyNegMap.find(key) : SimplifyMap.find(key);
+ itend = pushNeg ? SimplifyNegMap.end() : SimplifyMap.end();
+
+ if(it != itend) {
+ output = it->second;
+ CountersAndStats("Successful_CheckSimplifyMap");
+ return true;
+ }
+
+ if(pushNeg && (it = SimplifyMap.find(key)) != SimplifyMap.end()) {
+ output =
+ (ASTFalse == it->second) ?
+ ASTTrue :
+ (ASTTrue == it->second) ? ASTFalse : CreateNode(NOT, it->second);
+ CountersAndStats("2nd_Successful_CheckSimplifyMap");
+ return true;
+ }
+
+ return false;
+ }
+
+ void BeevMgr::UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg) {
+ if(pushNeg)
+ SimplifyNegMap[key] = value;
+ else
+ SimplifyMap[key] = value;
+ }
+
+ bool BeevMgr::CheckSubstitutionMap(const ASTNode& key, ASTNode& output) {
+ ASTNodeMap::iterator it;
+ if((it = SolverMap.find(key)) != SolverMap.end()) {
+ output = it->second;
+ return true;
+ }
+ return false;
+ }
+
+ bool BeevMgr::CheckSubstitutionMap(const ASTNode& key) {
+ if(SolverMap.find(key) != SolverMap.end())
+ return true;
+ else
+ return false;
+ }
+
+ bool BeevMgr::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1) {
+ int i = TermOrder(e0,e1);
+ if(0 == i)
+ return false;
+
+ //e0 is of the form READ(Arr,const), and e1 is const, or
+ //e0 is of the form var, and e1 is const
+ if(1 == i && !CheckSubstitutionMap(e0)) {
+ SolverMap[e0] = e1;
+ return true;
+ }
+
+ //e1 is of the form READ(Arr,const), and e0 is const, or
+ //e1 is of the form var, and e0 is const
+ if (-1 == i && !CheckSubstitutionMap(e1)) {
+ SolverMap[e1] = e0;
+ return true;
+ }
+
+ return false;
+ }
+
+ bool BeevMgr::CheckMultInverseMap(const ASTNode& key, ASTNode& output) {
+ ASTNodeMap::iterator it;
+ if((it = MultInverseMap.find(key)) != MultInverseMap.end()) {
+ output = it->second;
+ return true;
+ }
+ return false;
+ }
+
+ void BeevMgr::UpdateMultInverseMap(const ASTNode& key, const ASTNode& value) {
+ MultInverseMap[key] = value;
+ }
+
+
+ bool BeevMgr::CheckAlwaysTrueFormMap(const ASTNode& key) {
+ ASTNodeSet::iterator it = AlwaysTrueFormMap.find(key);
+ ASTNodeSet::iterator itend = AlwaysTrueFormMap.end();
+
+ if(it != itend) {
+ //cerr << "found:" << *it << endl;
+ CountersAndStats("Successful_CheckAlwaysTrueFormMap");
+ return true;
+ }
+
+ return false;
+ }
+
+ void BeevMgr::UpdateAlwaysTrueFormMap(const ASTNode& key) {
+ AlwaysTrueFormMap.insert(key);
+ }
+
+ //if a is READ(Arr,const) or SYMBOL, and b is BVCONST then return 1
+ //if b is READ(Arr,const) or SYMBOL, and a is BVCONST then return -1
+ //
+ //else return 0 by default
+ int BeevMgr::TermOrder(const ASTNode& a, const ASTNode& b) {
+ Kind k1 = a.GetKind();
+ Kind k2 = b.GetKind();
+
+ //a is of the form READ(Arr,const), and b is const, or
+ //a is of the form var, and b is const
+ if((k1 == READ
+ &&
+ a[0].GetKind() == SYMBOL &&
+ a[1].GetKind() == BVCONST
+ )
+ &&
+ (k2 == BVCONST)
+ )
+ return 1;
+
+ if(k1 == SYMBOL)
+ return 1;
+
+ //b is of the form READ(Arr,const), and a is const, or
+ //b is of the form var, and a is const
+ if((k1 == BVCONST)
+ &&
+ ((k2 == READ
+ &&
+ b[0].GetKind() == SYMBOL &&
+ b[1].GetKind() == BVCONST
+ )
+ ||
+ k2 == SYMBOL
+ ))
+ return -1;
+ return 0;
+ }
+
+ //This function records all the const-indices seen so far for each
+ //array. It populates the map '_arrayname_readindices' whose key is
+ //the arrayname, and vlaue is a vector of read-indices.
+ //
+ //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
+ //and index is a BVCONST.
+ //
+ //Since these arrayreads are being nuked and recorded in the
+ //substitutionmap, we have to also record the fact that each
+ //arrayread (e0 is of the form READ(Arr,const) here is represented
+ //by a BVCONST (e1). This is necessary for later Leibnitz Axiom
+ //generation
+ void BeevMgr::FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1) {
+ int i = TermOrder(e0,e1);
+ if(0 == i) return;
+
+ if(1 == i && e0.GetKind() != SYMBOL && !CheckSubstitutionMap(e0)) {
+ _arrayname_readindices[e0[0]].push_back(e0[1]);
+ //e0 is the array read : READ(A,i) and e1 is a bvconst
+ _arrayread_symbol[e0] = e1;
+ return;
+ }
+ if(-1 == i && e1.GetKind() != SYMBOL && !CheckSubstitutionMap(e1)) {
+ _arrayname_readindices[e1[0]].push_back(e1[1]);
+ //e0 is the array read : READ(A,i) and e1 is a bvconst
+ _arrayread_symbol[e1] = e0;
+ return;
+ }
+ }
+
+ ASTNode BeevMgr::SimplifyFormula_NoRemoveWrites(const ASTNode& b, bool pushNeg) {
+ Begin_RemoveWrites = false;
+ ASTNode out = SimplifyFormula(b,pushNeg);
+ return out;
+ }
+
+ ASTNode BeevMgr::SimplifyFormula_TopLevel(const ASTNode& b, bool pushNeg) {
+ SimplifyMap.clear();
+ SimplifyNegMap.clear();
+ ASTNode out = SimplifyFormula(b,pushNeg);
+ SimplifyMap.clear();
+ SimplifyNegMap.clear();
+ return out;
+ }
+
+ ASTNode BeevMgr::SimplifyFormula(const ASTNode& b, bool pushNeg){
+ if(!optimize)
+ return b;
+
+ Kind kind = b.GetKind();
+ if(BOOLEAN_TYPE != b.GetType()) {
+ FatalError(" SimplifyFormula: You have input a nonformula kind: ",ASTUndefined,kind);
+ }
+
+ ASTNode a = b;
+ ASTVec ca = a.GetChildren();
+ if(!(IMPLIES == kind ||
+ ITE == kind ||
+ isAtomic(kind))) {
+ SortByExprNum(ca);
+ a = CreateNode(kind,ca);
+ }
+
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ switch(kind){
+ case AND:
+ case OR:
+ output = SimplifyAndOrFormula(a,pushNeg);
+ break;
+ case NOT:
+ output = SimplifyNotFormula(a,pushNeg);
+ break;
+ case XOR:
+ output = SimplifyXorFormula(a,pushNeg);
+ break;
+ case NAND:
+ output = SimplifyNandFormula(a,pushNeg);
+ break;
+ case NOR:
+ output = SimplifyNorFormula(a,pushNeg);
+ break;
+ case IFF:
+ output = SimplifyIffFormula(a,pushNeg);
+ break;
+ case IMPLIES:
+ output = SimplifyImpliesFormula(a,pushNeg);
+ break;
+ case ITE:
+ output = SimplifyIteFormula(a,pushNeg);
+ break;
+ default:
+ //kind can be EQ,NEQ,BVLT,BVLE,... or a propositional variable
+ output = SimplifyAtomicFormula(a,pushNeg);
+ //output = pushNeg ? CreateNode(NOT,a) : a;
+ break;
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output, pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyAtomicFormula(const ASTNode& a, bool pushNeg) {
+ if(!optimize) {
+ return a;
+ }
+
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,pushNeg)) {
+ return output;
+ }
+
+ ASTNode left,right;
+ if(a.Degree() == 2) {
+ //cerr << "Input to simplifyterm: left: " << a[0] << endl;
+ left = SimplifyTerm(a[0]);
+ //cerr << "Output of simplifyterm:left: " << left << endl;
+ //cerr << "Input to simplifyterm: right: " << a[1] << endl;
+ right = SimplifyTerm(a[1]);
+ //cerr << "Output of simplifyterm:left: " << right << endl;
+ }
+
+ Kind kind = a.GetKind();
+ switch(kind) {
+ case TRUE:
+ output = pushNeg ? ASTFalse : ASTTrue;
+ break;
+ case FALSE:
+ output = pushNeg ? ASTTrue : ASTFalse;
+ break;
+ case SYMBOL:
+ if(!CheckSolverMap(a,output)) {
+ output = a;
+ }
+ output = pushNeg ? CreateNode(NOT,output) : output;
+ break;
+ case BVGETBIT: {
+ ASTNode term = SimplifyTerm(a[0]);
+ ASTNode thebit = a[1];
+ ASTNode zero = CreateZeroConst(1);
+ ASTNode one = CreateOneConst(1);
+ ASTNode getthebit = SimplifyTerm(CreateTerm(BVEXTRACT,1,term,thebit,thebit));
+ if(getthebit == zero)
+ output = pushNeg ? ASTTrue : ASTFalse;
+ else if(getthebit == one)
+ output = pushNeg ? ASTFalse : ASTTrue;
+ else {
+ output = CreateNode(BVGETBIT,term,thebit);
+ output = pushNeg ? CreateNode(NOT,output) : output;
+ }
+ break;
+ }
+ case EQ:{
+ output = CreateSimplifiedEQ(left,right);
+ output = LhsMinusRhs(output);
+ output = ITEOpt_InEqs(output);
+ if(output == ASTTrue)
+ output = pushNeg ? ASTFalse : ASTTrue;
+ else if (output == ASTFalse)
+ output = pushNeg ? ASTTrue : ASTFalse;
+ else
+ output = pushNeg ? CreateNode(NOT,output) : output;
+ break;
+ }
+ case NEQ: {
+ output = CreateSimplifiedEQ(left,right);
+ output = LhsMinusRhs(output);
+ if(output == ASTTrue)
+ output = pushNeg ? ASTTrue : ASTFalse;
+ else if (output == ASTFalse)
+ output = pushNeg ? ASTFalse : ASTTrue;
+ else
+ output = pushNeg ? output : CreateNode(NOT,output);
+ break;
+ }
+ case BVLT:
+ case BVLE:
+ case BVGT:
+ case BVGE:
+ case BVSLT:
+ case BVSLE:
+ case BVSGT:
+ case BVSGE: {
+ //output = CreateNode(kind,left,right);
+ //output = pushNeg ? CreateNode(NOT,output) : output;
+ output = CreateSimplifiedINEQ(kind,left,right,pushNeg);
+ break;
+ }
+ default:
+ FatalError("SimplifyAtomicFormula: NO atomic formula of the kind: ",ASTUndefined,kind);
+ break;
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ } //end of SimplifyAtomicFormula()
+
+ ASTNode BeevMgr::CreateSimplifiedINEQ(Kind k,
+ const ASTNode& left,
+ const ASTNode& right,
+ bool pushNeg) {
+ ASTNode output;
+ if(BVCONST == left.GetKind() && BVCONST == right.GetKind()) {
+ output = BVConstEvaluator(CreateNode(k,left,right));
+ output = pushNeg ? (ASTFalse == output) ? ASTTrue : ASTFalse : output;
+ return output;
+ }
+
+ unsigned len = left.GetValueWidth();
+ ASTNode zero = CreateZeroConst(len);
+ ASTNode one = CreateOneConst(len);
+ ASTNode max = CreateMaxConst(len);
+ switch(k){
+ case BVLT:
+ if(right == zero) {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else if(left == right) {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else if(one == right) {
+ output = CreateSimplifiedEQ(left,zero);
+ output = pushNeg ? CreateNode(NOT,output) : output;
+ }
+ else {
+ output = pushNeg ? CreateNode(BVLE,right,left) : CreateNode(BVLT,left,right);
+ }
+ break;
+ case BVLE:
+ if(left == zero) {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if(left == right) {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if(max == right) {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if(zero == right) {
+ output = CreateSimplifiedEQ(left,zero);
+ output = pushNeg ? CreateNode(NOT,output) : output;
+ }
+ else {
+ output = pushNeg ? CreateNode(BVLT,right,left) : CreateNode(BVLE,left,right);
+ }
+ break;
+ case BVGT:
+ if(left == zero) {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else if(left == right) {
+ output = pushNeg ? ASTTrue : ASTFalse;
+ }
+ else {
+ output = pushNeg ? CreateNode(BVLE,left,right) : CreateNode(BVLT,right,left);
+ }
+ break;
+ case BVGE:
+ if(right == zero) {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else if(left == right) {
+ output = pushNeg ? ASTFalse : ASTTrue;
+ }
+ else {
+ output = pushNeg ? CreateNode(BVLT,left,right) : CreateNode(BVLE,right,left);
+ }
+ break;
+ case BVSLT:
+ case BVSLE:
+ case BVSGE:
+ case BVSGT: {
+ output = CreateNode(k,left,right);
+ output = pushNeg ? CreateNode(NOT,output) : output;
+ }
+ break;
+ default:
+ FatalError("Wrong Kind");
+ break;
+ }
+
+ return output;
+ }
+
+ //takes care of some simple ITE Optimizations in the context of equations
+ ASTNode BeevMgr::ITEOpt_InEqs(const ASTNode& in) {
+ CountersAndStats("ITEOpts_InEqs");
+
+ if(!(EQ == in.GetKind() && optimize)) {
+ return in;
+ }
+
+ ASTNode output;
+ if(CheckSimplifyMap(in,output,false)) {
+ return output;
+ }
+
+ ASTNode in1 = in[0];
+ ASTNode in2 = in[1];
+ Kind k1 = in1.GetKind();
+ Kind k2 = in2.GetKind();
+ if(in1 == in2) {
+ //terms are syntactically the same
+ output = ASTTrue;
+ }
+ else if(BVCONST == k1 && BVCONST == k2) {
+ //here the terms are definitely not syntactically equal but may
+ //be semantically equal.
+ output = ASTFalse;
+ }
+ else if(ITE == k1 &&
+ BVCONST == in1[1].GetKind() &&
+ BVCONST == in1[2].GetKind() && BVCONST == k2) {
+ //if one side is a BVCONST and the other side is an ITE over
+ //BVCONST then we can do the following optimization:
+ //
+ // c = ITE(cond,c,d) <=> cond
+ //
+ // similarly ITE(cond,c,d) = c <=> cond
+ //
+ // c = ITE(cond,d,c) <=> NOT(cond)
+ //
+ //similarly ITE(cond,d,c) = d <=> NOT(cond)
+ ASTNode cond = in1[0];
+ if(in1[1] == in2) {
+ //ITE(cond, c, d) = c <=> cond
+ output = cond;
+ }
+ else if(in1[2] == in2) {
+ cond = SimplifyFormula(cond,true);
+ output = cond;
+ }
+ else {
+ //last resort is to CreateNode
+ output = CreateNode(EQ,in1,in2);
+ }
+ }
+ else if(ITE == k2 &&
+ BVCONST == in2[1].GetKind() &&
+ BVCONST == in2[2].GetKind() && BVCONST == k1) {
+ ASTNode cond = in2[0];
+ if(in2[1] == in1) {
+ //ITE(cond, c, d) = c <=> cond
+ output = cond;
+ }
+ else if(in2[2] == in1) {
+ cond = SimplifyFormula(cond,true);
+ output = cond;
+ }
+ else {
+ //last resort is to CreateNode
+ output = CreateNode(EQ,in1,in2);
+ }
+ }
+ else {
+ //last resort is to CreateNode
+ output = CreateNode(EQ,in1,in2);
+ }
+
+ UpdateSimplifyMap(in,output,false);
+ return output;
+ } //End of ITEOpts_InEqs()
+
+ //Tries to simplify the input to TRUE/FALSE. if it fails, then
+ //return the constructed equality
+ ASTNode BeevMgr::CreateSimplifiedEQ(const ASTNode& in1, const ASTNode& in2) {
+ CountersAndStats("CreateSimplifiedEQ");
+ Kind k1 = in1.GetKind();
+ Kind k2 = in2.GetKind();
+
+ if(!optimize) {
+ return CreateNode(EQ,in1,in2);
+ }
+
+ if(in1 == in2)
+ //terms are syntactically the same
+ return ASTTrue;
+
+ //here the terms are definitely not syntactically equal but may be
+ //semantically equal.
+ if(BVCONST == k1 && BVCONST == k2)
+ return ASTFalse;
+
+ //last resort is to CreateNode
+ return CreateNode(EQ,in1,in2);
+ }
+
+ //accepts cond == t1, then part is t2, and else part is t3
+ ASTNode BeevMgr::CreateSimplifiedTermITE(const ASTNode& in0,
+ const ASTNode& in1, const ASTNode& in2) {
+ ASTNode t0 = in0;
+ ASTNode t1 = in1;
+ ASTNode t2 = in2;
+ CountersAndStats("CreateSimplifiedITE");
+ if(!optimize) {
+ if(t1.GetValueWidth() != t2.GetValueWidth()) {
+ cerr << "t2 is : = " << t2;
+ FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
+ }
+ if(t1.GetIndexWidth() != t2.GetIndexWidth()) {
+ cerr << "t2 is : = " << t2;
+ FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
+ }
+ return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
+ }
+
+ if(t0 == ASTTrue)
+ return t1;
+ if (t0 == ASTFalse)
+ return t2;
+ if(t1 == t2)
+ return t1;
+ if(CheckAlwaysTrueFormMap(t0)) {
+ return t1;
+ }
+ if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
+ (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
+ return t2;
+ }
+
+ return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
+ }
+
+ ASTNode BeevMgr::SimplifyAndOrFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output;
+ //cerr << "input:\n" << a << endl;
+
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ ASTVec c, outvec;
+ c = a.GetChildren();
+ ASTNode flat = FlattenOneLevel(a);
+ c = flat.GetChildren();
+ SortByExprNum(c);
+
+ Kind k = a.GetKind();
+ bool isAnd = (k == AND) ? true : false;
+
+ ASTNode annihilator = isAnd ?
+ (pushNeg ? ASTTrue : ASTFalse):
+ (pushNeg ? ASTFalse : ASTTrue);
+
+ ASTNode identity = isAnd ?
+ (pushNeg ? ASTFalse : ASTTrue):
+ (pushNeg ? ASTTrue : ASTFalse);
+
+ //do the work
+ ASTVec::const_iterator next_it;
+ for(ASTVec::const_iterator i=c.begin(),iend=c.end();i!=iend;i++) {
+ ASTNode aaa = *i;
+ next_it = i+1;
+ bool nextexists = (next_it < iend);
+
+ aaa = SimplifyFormula(aaa,pushNeg);
+ if(annihilator == aaa) {
+ //memoize
+ UpdateSimplifyMap(*i,annihilator,pushNeg);
+ UpdateSimplifyMap(a, annihilator,pushNeg);
+ //cerr << "annihilator1: output:\n" << annihilator << endl;
+ return annihilator;
+ }
+ ASTNode bbb = ASTFalse;
+ if(nextexists) {
+ bbb = SimplifyFormula(*next_it,pushNeg);
+ }
+ if(nextexists && bbb == aaa) {
+ //skip the duplicate aaa. *next_it will be included
+ }
+ else if(nextexists &&
+ ((bbb.GetKind() == NOT && bbb[0] == aaa))) {
+ //memoize
+ UpdateSimplifyMap(a, annihilator,pushNeg);
+ //cerr << "annihilator2: output:\n" << annihilator << endl;
+ return annihilator;
+ }
+ else if(identity == aaa) {
+ // //drop identites
+ }
+ else if((!isAnd && !pushNeg) ||
+ (isAnd && pushNeg)) {
+ outvec.push_back(aaa);
+ }
+ else if((isAnd && !pushNeg) ||
+ (!isAnd && pushNeg)) {
+ outvec.push_back(aaa);
+ }
+ else {
+ outvec.push_back(aaa);
+ }
+ }
+
+ switch(outvec.size()) {
+ case 0: {
+ //only identities were dropped
+ output = identity;
+ break;
+ }
+ case 1: {
+ output = SimplifyFormula(outvec[0],false);
+ break;
+ }
+ default: {
+ output = (isAnd) ?
+ (pushNeg ? CreateNode(OR,outvec) : CreateNode(AND,outvec)):
+ (pushNeg ? CreateNode(AND,outvec) : CreateNode(OR,outvec));
+ //output = FlattenOneLevel(output);
+ break;
+ }
+ }
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ //cerr << "output:\n" << output << endl;
+ return output;
+ } //end of SimplifyAndOrFormula
+
+
+ ASTNode BeevMgr::SimplifyNotFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ if(!(a.Degree() == 1 && NOT == a.GetKind()))
+ FatalError("SimplifyNotFormula: input vector with more than 1 node",ASTUndefined);
+
+ //if pushNeg is set then there is NOT on top
+ unsigned int NotCount = pushNeg ? 1 : 0;
+ ASTNode o = a;
+ //count the number of NOTs in 'a'
+ while(NOT == o.GetKind()) {
+ o = o[0];
+ NotCount++;
+ }
+
+ //pushnegation if there are odd number of NOTs
+ bool pn = (NotCount % 2 == 0) ? false : true;
+
+ if(CheckAlwaysTrueFormMap(o)) {
+ output = pn ? ASTFalse : ASTTrue;
+ return output;
+ }
+
+ if(CheckSimplifyMap(o,output,pn)) {
+ return output;
+ }
+
+ if (ASTTrue == o) {
+ output = pn ? ASTFalse : ASTTrue;
+ }
+ else if (ASTFalse == o) {
+ output = pn ? ASTTrue : ASTFalse;
+ }
+ else {
+ output = SimplifyFormula(o,pn);
+ }
+ //memoize
+ UpdateSimplifyMap(o,output,pn);
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyXorFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ if (a.GetChildren().size() > 2) {
+ FatalError("Simplify got an XOR with more than two children.");
+ }
+
+ ASTNode a0 = SimplifyFormula(a[0],false);
+ ASTNode a1 = SimplifyFormula(a[1],false);
+ output = pushNeg ? CreateNode(IFF,a0,a1) : CreateNode(XOR,a0,a1);
+
+ if(XOR == output.GetKind()) {
+ a0 = output[0];
+ a1 = output[1];
+ if(a0 == a1)
+ output = ASTFalse;
+ else if((a0 == ASTTrue && a1 == ASTFalse) ||
+ (a0 == ASTFalse && a1 == ASTTrue))
+ output = ASTTrue;
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyNandFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output,a0,a1;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ //the two NOTs cancel out
+ if(pushNeg) {
+ a0 = SimplifyFormula(a[0],false);
+ a1 = SimplifyFormula(a[1],false);
+ output = CreateNode(AND,a0,a1);
+ }
+ else {
+ //push the NOT implicit in the NAND
+ a0 = SimplifyFormula(a[0],true);
+ a1 = SimplifyFormula(a[1],true);
+ output = CreateNode(OR,a0,a1);
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyNorFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output,a0,a1;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ //the two NOTs cancel out
+ if(pushNeg) {
+ a0 = SimplifyFormula(a[0],false);
+ a1 = SimplifyFormula(a[1],false);
+ output = CreateNode(OR,a0,a1);
+ }
+ else {
+ //push the NOT implicit in the NAND
+ a0 = SimplifyFormula(a[0],true);
+ a1 = SimplifyFormula(a[1],true);
+ output = CreateNode(AND,a0,a1);
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyImpliesFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ if(!(a.Degree()==2 && IMPLIES==a.GetKind()))
+ FatalError("SimplifyImpliesFormula: vector with wrong num of nodes",ASTUndefined);
+
+ ASTNode c0,c1;
+ if(pushNeg) {
+ c0 = SimplifyFormula(a[0],false);
+ c1 = SimplifyFormula(a[1],true);
+ output = CreateNode(AND,c0,c1);
+ }
+ else {
+ c0 = SimplifyFormula(a[0],false);
+ c1 = SimplifyFormula(a[1],false);
+ if(ASTFalse == c0) {
+ output = ASTTrue;
+ }
+ else if (ASTTrue == c0) {
+ output = c1;
+ }
+ else if (c0 == c1) {
+ output = ASTTrue;
+ }
+ else if(CheckAlwaysTrueFormMap(c0)) {
+ // c0 AND (~c0 OR c1) <==> c1
+ //
+ //applying modus ponens
+ output = c1;
+ }
+ else if(CheckAlwaysTrueFormMap(c1) ||
+ CheckAlwaysTrueFormMap(CreateNode(NOT,c0)) ||
+ (NOT == c0.GetKind() && CheckAlwaysTrueFormMap(c0[0]))) {
+ //(~c0 AND (~c0 OR c1)) <==> TRUE
+ //
+ //(c0 AND ~c0->c1) <==> TRUE
+ output = ASTTrue;
+ }
+ else if (CheckAlwaysTrueFormMap(CreateNode(NOT,c1)) ||
+ (NOT == c1.GetKind() && CheckAlwaysTrueFormMap(c1[0]))) {
+ //(~c1 AND c0->c1) <==> (~c1 AND ~c1->~c0) <==> ~c0
+ //(c1 AND c0->~c1) <==> (c1 AND c1->~c0) <==> ~c0
+ output = CreateNode(NOT,c0);
+ }
+ else {
+ if(NOT == c0.GetKind()) {
+ output = CreateNode(OR,c0[0],c1);
+ }
+ else {
+ output = CreateNode(OR,CreateNode(NOT,c0),c1);
+ }
+ }
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyIffFormula(const ASTNode& a, bool pushNeg) {
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,pushNeg))
+ return output;
+
+ if(!(a.Degree()==2 && IFF==a.GetKind()))
+ FatalError("SimplifyIffFormula: vector with wrong num of nodes",ASTUndefined);
+
+ ASTNode c0 = a[0];
+ ASTNode c1 = SimplifyFormula(a[1],false);
+
+ if(pushNeg)
+ c0 = SimplifyFormula(c0,true);
+ else
+ c0 = SimplifyFormula(c0,false);
+
+ if(ASTTrue == c0) {
+ output = c1;
+ }
+ else if (ASTFalse == c0) {
+ output = SimplifyFormula(c1,true);
+ }
+ else if (ASTTrue == c1) {
+ output = c0;
+ }
+ else if (ASTFalse == c1) {
+ output = SimplifyFormula(c0,true);
+ }
+ else if (c0 == c1) {
+ output = ASTTrue;
+ }
+ else if((NOT == c0.GetKind() && c0[0] == c1) ||
+ (NOT == c1.GetKind() && c0 == c1[0])) {
+ output = ASTFalse;
+ }
+ else if(CheckAlwaysTrueFormMap(c0)) {
+ output = c1;
+ }
+ else if(CheckAlwaysTrueFormMap(c1)) {
+ output = c0;
+ }
+ else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c0))) {
+ output = CreateNode(NOT,c1);
+ }
+ else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c1))) {
+ output = CreateNode(NOT,c0);
+ }
+ else {
+ output = CreateNode(IFF,c0,c1);
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ ASTNode BeevMgr::SimplifyIteFormula(const ASTNode& b, bool pushNeg) {
+ if(!optimize)
+ return b;
+
+ ASTNode output;
+ if(CheckSimplifyMap(b,output,pushNeg))
+ return output;
+
+ if(!(b.Degree() == 3 && ITE == b.GetKind()))
+ FatalError("SimplifyIteFormula: vector with wrong num of nodes",ASTUndefined);
+
+ ASTNode a = b;
+ ASTNode t0 = SimplifyFormula(a[0],false);
+ ASTNode t1,t2;
+ if(pushNeg) {
+ t1 = SimplifyFormula(a[1],true);
+ t2 = SimplifyFormula(a[2],true);
+ }
+ else {
+ t1 = SimplifyFormula(a[1],false);
+ t2 = SimplifyFormula(a[2],false);
+ }
+
+ if(ASTTrue == t0) {
+ output = t1;
+ }
+ else if (ASTFalse == t0) {
+ output = t2;
+ }
+ else if (t1 == t2) {
+ output = t1;
+ }
+ else if(ASTTrue == t1 && ASTFalse == t2) {
+ output = t0;
+ }
+ else if(ASTFalse == t1 && ASTTrue == t2) {
+ output = SimplifyFormula(t0,true);
+ }
+ else if(ASTTrue == t1) {
+ output = CreateNode(OR,t0,t2);
+ }
+ else if(ASTFalse == t1) {
+ output = CreateNode(AND,CreateNode(NOT,t0),t2);
+ }
+ else if(ASTTrue == t2) {
+ output = CreateNode(OR,CreateNode(NOT,t0),t1);
+ }
+ else if(ASTFalse == t2) {
+ output = CreateNode(AND,t0,t1);
+ }
+ else if(CheckAlwaysTrueFormMap(t0)) {
+ output = t1;
+ }
+ else if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
+ (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
+ output = t2;
+ }
+ else {
+ output = CreateNode(ITE,t0,t1,t2);
+ }
+
+ //memoize
+ UpdateSimplifyMap(a,output,pushNeg);
+ return output;
+ }
+
+ //one level deep flattening
+ ASTNode BeevMgr::FlattenOneLevel(const ASTNode& a) {
+ Kind k = a.GetKind();
+ if(!(BVPLUS == k ||
+ AND == k || OR == k
+ //|| BVAND == k
+ //|| BVOR == k
+ )
+ ) {
+ return a;
+ }
+
+ ASTNode output;
+ // if(CheckSimplifyMap(a,output,false)) {
+ // //check memo table
+ // //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ // return output;
+ // }
+
+ ASTVec c = a.GetChildren();
+ ASTVec o;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode aaa = *it;
+ if(k == aaa.GetKind()) {
+ ASTVec ac = aaa.GetChildren();
+ o.insert(o.end(),ac.begin(),ac.end());
+ }
+ else
+ o.push_back(aaa);
+ }
+
+ if(is_Form_kind(k))
+ output = CreateNode(k,o);
+ else
+ output = CreateTerm(k,a.GetValueWidth(),o);
+
+ //UpdateSimplifyMap(a,output,false);
+ return output;
+ //memoize
+ } //end of flattenonelevel()
+
+ ASTNode BeevMgr::SimplifyTerm_TopLevel(const ASTNode& b) {
+ SimplifyMap.clear();
+ SimplifyNegMap.clear();
+ ASTNode out = SimplifyTerm(b);
+ SimplifyNegMap.clear();
+ SimplifyMap.clear();
+ return out;
+ }
+
+ //This function simplifies terms based on their kind
+ ASTNode BeevMgr::SimplifyTerm(const ASTNode& inputterm) {
+ //cout << "SimplifyTerm: input: " << a << endl;
+ if(!optimize) {
+ return inputterm;
+ }
+
+ BVTypeCheck(inputterm);
+ ASTNode output;
+ if(wordlevel_solve && CheckSolverMap(inputterm,output)) {
+ //cout << "SimplifyTerm: output: " << output << endl;
+ return SimplifyTerm(output);
+ }
+
+ if(CheckSimplifyMap(inputterm,output,false)) {
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ Kind k = inputterm.GetKind();
+ if(!is_Term_kind(k)) {
+ FatalError("SimplifyTerm: You have input a Non-term",ASTUndefined);
+ }
+
+ unsigned int inputValueWidth = inputterm.GetValueWidth();
+ switch(k) {
+ case BVCONST:
+ output = inputterm;
+ break;
+ case SYMBOL:
+ if(CheckSolverMap(inputterm,output)) {
+ return SimplifyTerm(output);
+ }
+ output = inputterm;
+ break;
+ case BVMULT:
+ case BVPLUS:{
+ if(BVMULT == k && 2 != inputterm.Degree()) {
+ FatalError("SimplifyTerm: We assume that BVMULT is binary",inputterm);
+ }
+
+ ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+ SortByExprNum(c);
+ ASTVec constkids, nonconstkids;
+
+ //go through the childnodes, and separate constant and
+ //nonconstant nodes. combine the constant nodes using the
+ //constevaluator. if the resultant constant is zero and k ==
+ //BVPLUS, then ignore it (similarily for 1 and BVMULT). else,
+ //add the computed constant to the nonconst vector, flatten,
+ //sort, and create BVPLUS/BVMULT and return
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode aaa = SimplifyTerm(*it);
+ if(BVCONST == aaa.GetKind()) {
+ constkids.push_back(aaa);
+ }
+ else {
+ nonconstkids.push_back(aaa);
+ }
+ }
+
+ ASTNode one = CreateOneConst(inputValueWidth);
+ ASTNode max = CreateMaxConst(inputValueWidth);
+ ASTNode zero = CreateZeroConst(inputValueWidth);
+
+ //initialize constoutput to zero, in case there are no elements
+ //in constkids
+ ASTNode constoutput = (k == BVPLUS) ? zero : one;
+
+ if(1 == constkids.size()) {
+ //only one element in constkids
+ constoutput = constkids[0];
+ }
+ else if (1 < constkids.size()) {
+ //many elements in constkids. simplify it
+ constoutput = CreateTerm(k,inputterm.GetValueWidth(),constkids);
+ constoutput = BVConstEvaluator(constoutput);
+ }
+
+ if(BVMULT == k && zero == constoutput) {
+ output = zero;
+ }
+ else if(BVMULT == k &&
+ 1 == nonconstkids.size() &&
+ constoutput == max) {
+ //useful special case opt: when input is BVMULT(max_const,t),
+ //then output = BVUMINUS(t). this is easier on the bitblaster
+ output = CreateTerm(BVUMINUS,inputValueWidth,nonconstkids);
+ }
+ else {
+ if(0 < nonconstkids.size()) {
+ //nonconstkids is not empty. First, combine const and
+ //nonconstkids
+ if(BVPLUS == k && constoutput != zero) {
+ nonconstkids.push_back(constoutput);
+ }
+ else if(BVMULT == k && constoutput != one) {
+ nonconstkids.push_back(constoutput);
+ }
+
+ if(1 == nonconstkids.size()) {
+ //exactly one element in nonconstkids. output is exactly
+ //nonconstkids[0]
+ output = nonconstkids[0];
+ }
+ else {
+ //more than 1 element in nonconstkids. create BVPLUS term
+ SortByExprNum(nonconstkids);
+ output = CreateTerm(k,inputValueWidth,nonconstkids);
+ output = FlattenOneLevel(output);
+ output = DistributeMultOverPlus(output,true);
+ output = CombineLikeTerms(output);
+ }
+ }
+ else {
+ //nonconstkids was empty, all childnodes were constant, hence
+ //constoutput is the output.
+ output = constoutput;
+ }
+ }
+ if(BVMULT == output.GetKind()
+ || BVPLUS == output.GetKind()
+ ) {
+ ASTVec d = output.GetChildren();
+ SortByExprNum(d);
+ output = CreateTerm(output.GetKind(),output.GetValueWidth(),d);
+ }
+ break;
+ }
+ case BVSUB: {
+ ASTVec c = inputterm.GetChildren();
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ ASTNode a1 = SimplifyTerm(inputterm[1]);
+ unsigned int l = inputValueWidth;
+ if(a0 == a1)
+ output = CreateZeroConst(l);
+ else {
+ //covert x-y into x+(-y) and simplify. this transformation
+ //triggers more simplifications
+ a1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a1));
+ output = SimplifyTerm(CreateTerm(BVPLUS,l,a0,a1));
+ }
+ break;
+ }
+ case BVUMINUS: {
+ //important to treat BVUMINUS as a special case, because it
+ //helps in arithmetic transformations. e.g. x + BVUMINUS(x) is
+ //actually 0. One way to reveal this fact is to strip bvuminus
+ //out, and replace with something else so that combineliketerms
+ //can catch this fact.
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ Kind k1 = a0.GetKind();
+ unsigned int l = a0.GetValueWidth();
+ ASTNode one = CreateOneConst(l);
+ switch(k1) {
+ case BVUMINUS:
+ output = a0[0];
+ break;
+ case BVCONST: {
+ output = BVConstEvaluator(CreateTerm(BVUMINUS,l,a0));
+ break;
+ }
+ case BVNEG: {
+ output = SimplifyTerm(CreateTerm(BVPLUS,l,a0[0],one));
+ break;
+ }
+ case BVMULT: {
+ if(BVUMINUS == a0[0].GetKind()) {
+ output = CreateTerm(BVMULT,l,a0[0][0],a0[1]);
+ }
+ else if(BVUMINUS == a0[1].GetKind()) {
+ output = CreateTerm(BVMULT,l,a0[0],a0[1][0]);
+ }
+ else {
+ ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[0]));
+ output = CreateTerm(BVMULT,l,a00,a0[1]);
+ }
+ break;
+ }
+ case BVPLUS: {
+ //push BVUMINUS over all the monomials of BVPLUS. Simplify
+ //along the way
+ //
+ //BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
+ //BVUMINUS(a2x2) + ...
+ ASTVec c = a0.GetChildren();
+ ASTVec o;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ //Simplify(BVUMINUS(a1x1))
+ ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS,l,*it));
+ o.push_back(aaa);
+ }
+ //simplify the bvplus
+ output = SimplifyTerm(CreateTerm(BVPLUS,l,o));
+ break;
+ }
+ case BVSUB: {
+ //BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
+ output = SimplifyTerm(CreateTerm(BVSUB,l,a0[1],a0[0]));
+ break;
+ }
+ case ITE: {
+ //BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
+ ASTNode c = a0[0];
+ ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[1]));
+ ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[2]));
+ output = CreateSimplifiedTermITE(c,t1,t2);
+ break;
+ }
+ default: {
+ output = CreateTerm(BVUMINUS,l,a0);
+ break;
+ }
+ }
+ break;
+ }
+ case BVEXTRACT:{
+ //it is important to take care of wordlevel transformation in
+ //BVEXTRACT. it exposes oppurtunities for later simplification
+ //and solving (variable elimination)
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ Kind k1 = a0.GetKind();
+ unsigned int a_len = inputValueWidth;
+
+ //indices for BVEXTRACT
+ ASTNode i = inputterm[1];
+ ASTNode j = inputterm[2];
+ ASTNode zero = CreateBVConst(32,0);
+ //recall that the indices of BVEXTRACT are always 32 bits
+ //long. therefore doing a GetBVUnsigned is ok.
+ unsigned int i_val = GetUnsignedConst(i);
+ unsigned int j_val = GetUnsignedConst(j);
+
+ // a0[i:0] and len(a0)=i+1, then return a0
+ if(0 == j_val && a_len == a0.GetValueWidth())
+ return a0;
+
+ switch(k1) {
+ case BVCONST: {
+ //extract the constant
+ output = BVConstEvaluator(CreateTerm(BVEXTRACT,a_len,a0,i,j));
+ break;
+ }
+ case BVCONCAT:{
+ //assumes concatenation is binary
+ //
+ //input is of the form a0[i:j]
+ //
+ //a0 is the conatentation t at u, and a0[0] is t, and a0[1] is u
+ ASTNode t = a0[0];
+ ASTNode u = a0[1];
+ unsigned int len_a0 = a0.GetValueWidth();
+ unsigned int len_u = u.GetValueWidth();
+
+ if(len_u > i_val) {
+ //Apply the following rule:
+ // (t at u)[i:j] <==> u[i:j], if len(u) > i
+ //
+ output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
+ }
+ else if(len_a0 > i_val && j_val >= len_u) {
+ //Apply the rule:
+ // (t at u)[i:j] <==> t[i-len_u:j-len_u], if len(t at u) > i >= j >= len(u)
+ i = CreateBVConst(32, i_val - len_u);
+ j = CreateBVConst(32, j_val - len_u);
+ output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
+ }
+ else {
+ //Apply the rule:
+ // (t at u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
+ i = CreateBVConst(32,i_val-len_u);
+ ASTNode m = CreateBVConst(32, len_u-1);
+ t = SimplifyTerm(CreateTerm(BVEXTRACT,i_val-len_u+1,t,i,zero));
+ u = SimplifyTerm(CreateTerm(BVEXTRACT,len_u-j_val,u,m,j));
+ output = CreateTerm(BVCONCAT,a_len,t,u);
+ }
+ break;
+ }
+ case BVPLUS:
+ case BVMULT: {
+ // (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
+ //similar rule for BVPLUS
+ ASTVec c = a0.GetChildren();
+ ASTVec o;
+ for(ASTVec::iterator jt=c.begin(),jtend=c.end();jt!=jtend;jt++) {
+ ASTNode aaa = *jt;
+ aaa = SimplifyTerm(CreateTerm(BVEXTRACT,i_val+1,aaa,i,zero));
+ o.push_back(aaa);
+ }
+ output = CreateTerm(a0.GetKind(),i_val+1,o);
+ if(j_val != 0) {
+ //add extraction only if j is not zero
+ output = CreateTerm(BVEXTRACT,a_len,output,i,j);
+ }
+ break;
+ }
+ case BVAND:
+ case BVOR:
+ case BVXOR: {
+ //assumes these operators are binary
+ //
+ // (t op u)[i:j] <==> t[i:j] op u[i:j]
+ ASTNode t = a0[0];
+ ASTNode u = a0[1];
+ t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
+ u = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
+ BVTypeCheck(t);
+ BVTypeCheck(u);
+ output = CreateTerm(k1,a_len,t,u);
+ break;
+ }
+ case BVNEG:{
+ // (~t)[i:j] <==> ~(t[i:j])
+ ASTNode t = a0[0];
+ t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
+ output = CreateTerm(BVNEG,a_len,t);
+ break;
+ }
+ // case BVSX:{
+// //(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0
+// ASTNode t = a0[0];
+// unsigned int bvsx_len = a0.GetValueWidth();
+// if(bvsx_len < a_len) {
+// FatalError("SimplifyTerm: BVEXTRACT over BVSX:"
+// "the length of BVSX term must be greater than extract-len",inputterm);
+// }
+// if(j != zero) {
+// output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
+// }
+// else {
+// output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
+// }
+// break;
+// }
+ case ITE: {
+ ASTNode t0 = a0[0];
+ ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[1],i,j));
+ ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[2],i,j));
+ output = CreateSimplifiedTermITE(t0,t1,t2);
+ break;
+ }
+ default: {
+ output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
+ break;
+ }
+ }
+ break;
+ }
+ case BVNEG: {
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ unsigned len = inputValueWidth;
+ switch(a0.GetKind()) {
+ case BVCONST:
+ output = BVConstEvaluator(CreateTerm(BVNEG,len,a0));
+ break;
+ case BVNEG:
+ output = a0[0];
+ break;
+ // case ITE: {
+// ASTNode cond = a0[0];
+// ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
+// ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
+// output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
+// break;
+// }
+ default:
+ output = CreateTerm(BVNEG,len,a0);
+ break;
+ }
+ break;
+ }
+ case BVSX:{
+ //a0 is the expr which is being sign extended
+ ASTNode a0 = SimplifyTerm(inputterm[0]);
+ //a1 represents the length of the term BVSX(a0)
+ ASTNode a1 = inputterm[1];
+ //output length of the BVSX term
+ unsigned len = inputValueWidth;
+
+ if(a0.GetValueWidth() == len) {
+ //nothing to signextend
+ return a0;
+ }
+
+ switch(a0.GetKind()) {
+ case BVCONST:
+ output = BVConstEvaluator(CreateTerm(BVSX,len,a0,a1));
+ break;
+ case BVNEG:
+ output = CreateTerm(a0.GetKind(),len,CreateTerm(BVSX,len,a0[0],a1));
+ break;
+ case BVAND:
+ case BVOR:
+ //assuming BVAND and BVOR are binary
+ output = CreateTerm(a0.GetKind(),len,
+ CreateTerm(BVSX,len,a0[0],a1),
+ CreateTerm(BVSX,len,a0[1],a1));
+ break;
+ case BVPLUS: {
+ //BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
+ ASTVec c = a0.GetChildren();
+ bool returnflag = false;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ if(BVSX != it->GetKind()) {
+ returnflag = true;
+ break;
+ }
+ }
+ if(returnflag) {
+ output = CreateTerm(BVSX,len,a0,a1);
+ }
+ else {
+ ASTVec o;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode aaa = SimplifyTerm(CreateTerm(BVSX,len,*it,a1));
+ o.push_back(aaa);
+ }
+ output = CreateTerm(a0.GetKind(),len,o);
+ }
+ break;
+ }
+ case BVSX: {
+ //if you have BVSX(m,BVSX(n,a)) then you can drop the inner
+ //BVSX provided m is greater than n.
+ a0 = SimplifyTerm(a0[0]);
+ output = CreateTerm(BVSX,len,a0,a1);
+ break;
+ }
+ case ITE: {
+ ASTNode cond = a0[0];
+ ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX,len,a0[1],a1));
+ ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX,len,a0[2],a1));
+ output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
+ break;
+ }
+ default:
+ output = CreateTerm(BVSX,len,a0,a1);
+ break;
+ }
+ break;
+ }
+ case BVAND:
+ case BVOR:{
+ ASTNode max = CreateMaxConst(inputValueWidth);
+ ASTNode zero = CreateZeroConst(inputValueWidth);
+
+ ASTNode identity = (BVAND == k) ? max : zero;
+ ASTNode annihilator = (BVAND == k) ? zero : max;
+ ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+ SortByExprNum(c);
+ ASTVec o;
+ bool constant = true;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode aaa = SimplifyTerm(*it);
+ if(BVCONST != aaa.GetKind()) {
+ constant = false;
+ }
+
+ if(aaa == annihilator) {
+ output = annihilator;
+ //memoize
+ UpdateSimplifyMap(inputterm,output,false);
+ //cerr << "output of SimplifyTerm: " << output << endl;
+ return output;
+ }
+
+ if(aaa != identity) {
+ o.push_back(aaa);
+ }
+ }
+
+ switch(o.size()) {
+ case 0:
+ output = identity;
+ break;
+ case 1:
+ output = o[0];
+ break;
+ default:
+ SortByExprNum(o);
+ output = CreateTerm(k,inputValueWidth,o);
+ if(constant) {
+ output = BVConstEvaluator(output);
+ }
+ break;
+ }
+ break;
+ }
+ case BVCONCAT:{
+ ASTNode t = SimplifyTerm(inputterm[0]);
+ ASTNode u = SimplifyTerm(inputterm[1]);
+ Kind tkind = t.GetKind();
+ Kind ukind = u.GetKind();
+
+
+ if(BVCONST == tkind && BVCONST == ukind) {
+ output = BVConstEvaluator(CreateTerm(BVCONCAT,inputValueWidth,t,u));
+ }
+ else if(BVEXTRACT == tkind &&
+ BVEXTRACT == ukind &&
+ t[0] == u[0]) {
+ //to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
+ ASTNode t_hi = t[1];
+ ASTNode t_low = t[2];
+ ASTNode u_hi = u[1];
+ ASTNode u_low = u[2];
+ ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS,32,u_hi,CreateOneConst(32)));
+ if(t_low == c) {
+ output = CreateTerm(BVEXTRACT,inputValueWidth,t[0],t_hi,u_low);
+ }
+ else {
+ output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
+ }
+ }
+ else {
+ output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
+ }
+ break;
+ }
+ case BVXOR:
+ case BVXNOR:
+ case BVNAND:
+ case BVNOR:
+ case BVLEFTSHIFT:
+ case BVRIGHTSHIFT:
+ case BVVARSHIFT:
+ case BVSRSHIFT:
+ case BVDIV:
+ case BVMOD: {
+ ASTVec c = inputterm.GetChildren();
+ ASTVec o;
+ bool constant = true;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode aaa = SimplifyTerm(*it);
+ if(BVCONST != aaa.GetKind()) {
+ constant = false;
+ }
+ o.push_back(aaa);
+ }
+ output = CreateTerm(k,inputValueWidth,o);
+ if(constant)
+ output = BVConstEvaluator(output);
+ break;
+ }
+ case READ: {
+ ASTNode out1;
+ //process only if not in the substitution map. simplifymap
+ //has been checked already
+ if(!CheckSubstitutionMap(inputterm,out1)) {
+ if(WRITE == inputterm[0].GetKind()) {
+ //get rid of all writes
+ ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
+ out1 = nowrites;
+ }
+ else if (ITE == inputterm[0].GetKind()){
+ ASTNode cond = SimplifyFormula(inputterm[0][0],false);
+ ASTNode arr1 = SimplifyTerm(inputterm[0][1]);
+ ASTNode arr2 = SimplifyTerm(inputterm[0][2]);
+
+ ASTNode index = SimplifyTerm(inputterm[1]);
+
+ ASTNode read1 = CreateTerm(READ,inputValueWidth,arr1,index);
+ ASTNode read2 = CreateTerm(READ,inputValueWidth,arr2,index);
+ out1 = CreateSimplifiedTermITE(cond,read1,read2);
+ }
+ else {
+ //arr is a SYMBOL for sure
+ ASTNode arr = inputterm[0];
+ ASTNode index = SimplifyTerm(inputterm[1]);
+ out1 = CreateTerm(READ,inputValueWidth,arr,index);
+ }
+ }
+ //it is possible that after all the procesing the READ term
+ //reduces to READ(Symbol,const) and hence we should check the
+ //substitutionmap once again.
+ if(!CheckSubstitutionMap(out1,output))
+ output = out1;
+ break;
+ }
+ case ITE: {
+ ASTNode t0 = SimplifyFormula(inputterm[0],false);
+ ASTNode t1 = SimplifyTerm(inputterm[1]);
+ ASTNode t2 = SimplifyTerm(inputterm[2]);
+ output = CreateSimplifiedTermITE(t0,t1,t2);
+ break;
+ }
+ case SBVMOD:
+ case SBVDIV: {
+ ASTVec c = inputterm.GetChildren();
+ ASTVec o;
+ for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+ ASTNode aaa = SimplifyTerm(*it);
+ o.push_back(aaa);
+ }
+ output = CreateTerm(k,inputValueWidth,o);
+ break;
+ }
+ case WRITE:
+ default:
+ FatalError("SimplifyTerm: Control should never reach here:", inputterm, k);
+ return inputterm;
+ break;
+ }
+
+ //memoize
+ UpdateSimplifyMap(inputterm,output,false);
+ //cerr << "SimplifyTerm: output" << output << endl;
+ return output;
+ } //end of SimplifyTerm()
+
+
+ //At the end of each simplification call, we want the output to be
+ //always smaller or equal to the input in size.
+ void BeevMgr::CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output) {
+ //Don't do the check in optimized mode
+ if(optimize)
+ return;
+
+ if(NodeSize(a,true) < NodeSize(output,true)) {
+ cerr << "lhs := " << a << endl;
+ cerr << "NodeSize of lhs is: " << NodeSize(a, true) << endl;
+ cerr << endl;
+ cerr << "rhs := " << output << endl;
+ cerr << "NodeSize of rhs is: " << NodeSize(output, true) << endl;
+ FatalError("SimplifyFormula: The nodesize shoudl decrease from lhs to rhs: ",ASTUndefined);
+ }
+ }
+
+ //this function assumes that the input is a vector of childnodes of
+ //a BVPLUS term. it combines like terms and returns a bvplus
+ //term. e.g. 1.x + 2.x is converted to 3.x
+ ASTNode BeevMgr::CombineLikeTerms(const ASTNode& a) {
+ if(BVPLUS != a.GetKind())
+ return a;
+
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,false)) {
+ //check memo table
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ ASTVec c = a.GetChildren();
+ //map from variables to vector of constants
+ ASTNodeToVecMap vars_to_consts;
+ //vector to hold constants
+ ASTVec constkids;
+ ASTVec outputvec;
+
+ //useful constants
+ unsigned int len = c[0].GetValueWidth();
+ ASTNode one = CreateOneConst(len);
+ ASTNode zero = CreateZeroConst(len);
+ ASTNode max = CreateMaxConst(len);
+
+ //go over the childnodes of the input bvplus, and collect like
+ //terms in a map. the key of the map are the variables, and the
+ //values are stored in a ASTVec
+ for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
+ ASTNode aaa = *it;
+ if(SYMBOL == aaa.GetKind()) {
+ vars_to_consts[aaa].push_back(one);
+ }
+ else if(BVMULT == aaa.GetKind() &&
+ BVUMINUS == aaa[0].GetKind() &&
+ BVCONST == aaa[0][0].GetKind()) {
+ //(BVUMINUS(c))*(y) <==> compute(BVUMINUS(c))*y
+ ASTNode compute_const = BVConstEvaluator(aaa[0]);
+ vars_to_consts[aaa[1]].push_back(compute_const);
+ }
+ else if(BVMULT == aaa.GetKind() &&
+ BVUMINUS == aaa[1].GetKind() &&
+ BVCONST == aaa[0].GetKind()) {
+ //c*(BVUMINUS(y)) <==> compute(BVUMINUS(c))*y
+ ASTNode cccc = BVConstEvaluator(CreateTerm(BVUMINUS,len,aaa[0]));
+ vars_to_consts[aaa[1][0]].push_back(cccc);
+ }
+ else if(BVMULT == aaa.GetKind() && BVCONST == aaa[0].GetKind()) {
+ //assumes that BVMULT is binary
+ vars_to_consts[aaa[1]].push_back(aaa[0]);
+ }
+ else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[0].GetKind()) {
+ //(-1*x)*(y) <==> -1*(xy)
+ ASTNode cccc = CreateTerm(BVMULT,len,aaa[0][0],aaa[1]);
+ ASTVec cNodes = cccc.GetChildren();
+ SortByExprNum(cNodes);
+ vars_to_consts[cccc].push_back(max);
+ }
+ else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[1].GetKind()) {
+ //x*(-1*y) <==> -1*(xy)
+ ASTNode cccc = CreateTerm(BVMULT,len,aaa[0],aaa[1][0]);
+ ASTVec cNodes = cccc.GetChildren();
+ SortByExprNum(cNodes);
+ vars_to_consts[cccc].push_back(max);
+ }
+ else if(BVCONST == aaa.GetKind()) {
+ constkids.push_back(aaa);
+ }
+ else if(BVUMINUS == aaa.GetKind()) {
+ //helps to convert BVUMINUS into a BVMULT. here the max
+ //constant represents -1. this transformation allows us to
+ //conclude that x + BVUMINUS(x) is 0.
+ vars_to_consts[aaa[0]].push_back(max);
+ }
+ else
+ vars_to_consts[aaa].push_back(one);
+ } //end of for loop
+
+ //go over the map from variables to vector of values. combine the
+ //vector of values, multiply to the variable, and put the
+ //resultant monomial in the output BVPLUS.
+ for(ASTNodeToVecMap::iterator it=vars_to_consts.begin(),itend=vars_to_consts.end();
+ it!=itend;it++){
+ ASTVec ccc = it->second;
+
+ ASTNode constant;
+ if(1 < ccc.size()) {
+ constant = CreateTerm(BVPLUS,ccc[0].GetValueWidth(),ccc);
+ constant = BVConstEvaluator(constant);
+ }
+ else
+ constant = ccc[0];
+
+ //constant * var
+ ASTNode monom;
+ if(zero == constant)
+ monom = zero;
+ else if (one == constant)
+ monom = it->first;
+ else
+ monom =
+ SimplifyTerm(CreateTerm(BVMULT,constant.GetValueWidth(),constant,it->first));
+ if(zero != monom) {
+ outputvec.push_back(monom);
+ }
+ } //end of for loop
+
+ if(constkids.size() > 1) {
+ ASTNode output = CreateTerm(BVPLUS,constkids[0].GetValueWidth(),constkids);
+ output = BVConstEvaluator(output);
+ if(output != zero)
+ outputvec.push_back(output);
+ }
+ else if (constkids.size() == 1) {
+ if(constkids[0] != zero)
+ outputvec.push_back(constkids[0]);
+ }
+
+ if (outputvec.size() > 1) {
+ output = CreateTerm(BVPLUS,len,outputvec);
+ }
+ else if(outputvec.size() == 1) {
+ output = outputvec[0];
+ }
+ else {
+ output = zero;
+ }
+
+ //memoize
+ //UpdateSimplifyMap(a,output,false);
+ return output;
+ } //end of CombineLikeTerms()
+
+ //accepts lhs and rhs, and returns lhs - rhs = 0. The function
+ //assumes that lhs and rhs have already been simplified. although
+ //this assumption is not needed for correctness, it is essential for
+ //performance. The function also assumes that lhs is a BVPLUS
+ ASTNode BeevMgr::LhsMinusRhs(const ASTNode& eq) {
+ //if input is not an equality, simply return it
+ if(EQ != eq.GetKind())
+ return eq;
+
+ ASTNode lhs = eq[0];
+ ASTNode rhs = eq[1];
+ Kind k_lhs = lhs.GetKind();
+ Kind k_rhs = rhs.GetKind();
+ //either the lhs has to be a BVPLUS or the rhs has to be a
+ //BVPLUS
+ if(!(BVPLUS == k_lhs ||
+ BVPLUS == k_rhs ||
+ (BVMULT == k_lhs &&
+ BVMULT == k_rhs)
+ )) {
+ return eq;
+ }
+
+ ASTNode output;
+ if(CheckSimplifyMap(eq,output,false)) {
+ //check memo table
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ //if the lhs is not a BVPLUS, but the rhs is a BVPLUS, then swap
+ //the lhs and rhs
+ bool swap_flag = false;
+ if(BVPLUS != k_lhs && BVPLUS == k_rhs) {
+ ASTNode swap = lhs;
+ lhs = rhs;
+ rhs = swap;
+ swap_flag = true;
+ }
+
+ unsigned int len = lhs.GetValueWidth();
+ ASTNode zero = CreateZeroConst(len);
+ //right is -1*(rhs): Simplify(-1*rhs)
+ rhs = SimplifyTerm(CreateTerm(BVUMINUS,len,rhs));
+
+ ASTVec lvec = lhs.GetChildren();
+ ASTVec rvec = rhs.GetChildren();
+ ASTNode lhsplusrhs;
+ if(BVPLUS != lhs.GetKind() && BVPLUS != rhs.GetKind()) {
+ lhsplusrhs = CreateTerm(BVPLUS,len,lhs,rhs);
+ }
+ else if(BVPLUS == lhs.GetKind() && BVPLUS == rhs.GetKind()) {
+ //combine the childnodes of the left and the right
+ lvec.insert(lvec.end(),rvec.begin(),rvec.end());
+ lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
+ }
+ else if(BVPLUS == lhs.GetKind() && BVPLUS != rhs.GetKind()){
+ lvec.push_back(rhs);
+ lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
+ }
+ else {
+ //Control should never reach here
+ FatalError("LhsMinusRhs: Control should never reach here\n");
+ }
+
+ //combine like terms
+ output = CombineLikeTerms(lhsplusrhs);
+ output = SimplifyTerm(output);
+ //
+ //Now make output into: lhs-rhs = 0
+ output = CreateSimplifiedEQ(output,zero);
+ //sort if BVPLUS
+ if(BVPLUS == output.GetKind()) {
+ ASTVec outv = output.GetChildren();
+ SortByExprNum(outv);
+ output = CreateTerm(BVPLUS,len,outv);
+ }
+
+ //memoize
+ //UpdateSimplifyMap(eq,output,false);
+ return output;
+ } //end of LhsMinusRHS()
+
+ //THis function accepts a BVMULT(t1,t2) and distributes the mult
+ //over plus if either or both t1 and t2 are BVPLUSes.
+ //
+ // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
+ //
+ // (y1 + y2 + ...+ yn)*x <==> x*y1 + x*y2 + ... + x*yn
+ //
+ // The function assumes that the BVPLUSes have been flattened
+ ASTNode BeevMgr::DistributeMultOverPlus(const ASTNode& a, bool startdistribution) {
+ if(!startdistribution)
+ return a;
+ Kind k = a.GetKind();
+ if(BVMULT != k)
+ return a;
+
+ ASTNode left = a[0];
+ ASTNode right = a[1];
+ Kind left_kind = left.GetKind();
+ Kind right_kind = right.GetKind();
+
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,false)) {
+ //check memo table
+ //cerr << "output of SimplifyTerm Cache: " << output << endl;
+ return output;
+ }
+
+ //special case optimization: c1*(c2*t1) <==> (c1*c2)*t1
+ if(BVCONST == left_kind &&
+ BVMULT == right_kind &&
+ BVCONST == right[0].GetKind()) {
+ ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[0]));
+ c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[1]);
+ return c;
+ left = c[0];
+ right = c[1];
+ left_kind = left.GetKind();
+ right_kind = right.GetKind();
+ }
+
+ //special case optimization: c1*(t1*c2) <==> (c1*c2)*t1
+ if(BVCONST == left_kind &&
+ BVMULT == right_kind &&
+ BVCONST == right[1].GetKind()) {
+ ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[1]));
+ c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[0]);
+ return c;
+ left = c[0];
+ right = c[1];
+ left_kind = left.GetKind();
+ right_kind = right.GetKind();
+ }
+
+ //atleast one of left or right have to be BVPLUS
+ if(!(BVPLUS == left_kind || BVPLUS == right_kind)) {
+ return a;
+ }
+
+ //if left is BVPLUS and right is not, then swap left and right. we
+ //can do this since BVMULT is communtative
+ ASTNode swap;
+ if(BVPLUS == left_kind && BVPLUS != right_kind) {
+ swap = left;
+ left = right;
+ right = swap;
+ }
+ left_kind = left.GetKind();
+ right_kind = right.GetKind();
+
+ //by this point we are gauranteed that right is a BVPLUS, but left
+ //may not be
+ ASTVec rightnodes = right.GetChildren();
+ ASTVec outputvec;
+ unsigned len = a.GetValueWidth();
+ ASTNode zero = CreateZeroConst(len);
+ ASTNode one = CreateOneConst(len);
+ if(BVPLUS != left_kind) {
+ //if the multiplier is not a BVPLUS then we have a special case
+ // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
+ if(zero == left) {
+ outputvec.push_back(zero);
+ }
+ else if(one == left) {
+ outputvec.push_back(left);
+ }
+ else {
+ for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
+ j!=jend;j++) {
+ ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,left,*j));
+ outputvec.push_back(out);
+ }
+ }
+ }
+ else {
+ ASTVec leftnodes = left.GetChildren();
+ // (x1 + x2 + ... + xm)*(y1 + y2 + ...+ yn) <==> x1*y1 + x1*y2 +
+ // ... + x2*y1 + ... + xm*yn
+ for(ASTVec::iterator i=leftnodes.begin(),iend=leftnodes.end();
+ i!=iend;i++) {
+ ASTNode multiplier = *i;
+ for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
+ j!=jend;j++) {
+ ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,multiplier,*j));
+ outputvec.push_back(out);
+ }
+ }
+ }
+
+ //compute output here
+ if(outputvec.size() > 1) {
+ output = CombineLikeTerms(CreateTerm(BVPLUS,len,outputvec));
+ output = SimplifyTerm(output);
+ }
+ else
+ output = SimplifyTerm(outputvec[0]);
+
+ //memoize
+ //UpdateSimplifyMap(a,output,false);
+ return output;
+ } //end of distributemultoverplus()
+
+ //converts the BVSX(len, a0) operator into ITE( check top bit,
+ //extend a0 by 1, extend a0 by 0)
+ ASTNode BeevMgr::ConvertBVSXToITE(const ASTNode& a) {
+ if(BVSX != a.GetKind())
+ return a;
+
+ ASTNode output;
+ if(CheckSimplifyMap(a,output,false)) {
+ //check memo table
+ //cerr << "output of ConvertBVSXToITE Cache: " << output << endl;
+ return output;
+ }
+
+ ASTNode a0 = a[0];
+ unsigned a_len = a.GetValueWidth();
+ unsigned a0_len = a0.GetValueWidth();
+
+ if(a0_len > a_len){
+ FatalError("Trying to sign_extend a larger BV into a smaller BV");
+ return ASTUndefined; //to stop the compiler from producing bogus warnings
+ }
+
+ //sign extend
+ unsigned extensionlen = a_len-a0_len;
+ if(0 == extensionlen) {
+ UpdateSimplifyMap(a,output,false);
+ return a;
+ }
+
+ std::string ones;
+ for(unsigned c=0; c < extensionlen;c++)
+ ones += '1';
+ std::string zeros;
+ for(unsigned c=0; c < extensionlen;c++)
+ zeros += '0';
+
+ //string of oness of length extensionlen
+ BEEV::ASTNode BVOnes = CreateBVConst(ones.c_str(),2);
+ //string of zeros of length extensionlen
+ BEEV::ASTNode BVZeros = CreateBVConst(zeros.c_str(),2);
+
+ //string of ones BVCONCAT a0
+ BEEV::ASTNode concatOnes = CreateTerm(BEEV::BVCONCAT,a_len,BVOnes,a0);
+ //string of zeros BVCONCAT a0
+ BEEV::ASTNode concatZeros = CreateTerm(BEEV::BVCONCAT,a_len,BVZeros,a0);
+
+ //extract top bit of a0
+ BEEV::ASTNode hi = CreateBVConst(32,a0_len-1);
+ BEEV::ASTNode low = CreateBVConst(32,a0_len-1);
+ BEEV::ASTNode topBit = CreateTerm(BEEV::BVEXTRACT,1,a0,hi,low);
+
+ //compare topBit of a0 with 0bin1
+ BEEV::ASTNode condition = CreateSimplifiedEQ(CreateBVConst(1,1),topBit);
+
+ //ITE(topbit = 0bin1, 0bin1111...a0, 0bin000...a0)
+ output = CreateSimplifiedTermITE(condition,concatOnes,concatZeros);
+ UpdateSimplifyMap(a,output,false);
+ return output;
+ } //end of ConvertBVSXToITE()
+
+
+ ASTNode BeevMgr::RemoveWrites_TopLevel(const ASTNode& term) {
+ if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+ }
+
+ if(!Begin_RemoveWrites &&
+ !SimplifyWrites_InPlace_Flag &&
+ !start_abstracting) {
+ return term;
+ }
+ else if(!Begin_RemoveWrites &&
+ SimplifyWrites_InPlace_Flag &&
+ !start_abstracting) {
+ //return term;
+ return SimplifyWrites_InPlace(term);
+ }
+ else {
+ return RemoveWrites(term);
+ }
+ } //end of RemoveWrites_TopLevel()
+
+ ASTNode BeevMgr::SimplifyWrites_InPlace(const ASTNode& term) {
+ ASTNodeMultiSet WriteIndicesSeenSoFar;
+ bool SeenNonConstWriteIndex = false;
+
+ if(READ != term.GetKind() &&
+ WRITE != term[0].GetKind()) {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+ }
+
+ ASTNode output;
+ if(CheckSimplifyMap(term,output,false)) {
+ return output;
+ }
+
+ ASTVec writeIndices, writeValues;
+ unsigned int width = term.GetValueWidth();
+ ASTNode write = term[0];
+ unsigned indexwidth = write.GetIndexWidth();
+ ASTNode readIndex = SimplifyTerm(term[1]);
+
+ do {
+ ASTNode writeIndex = SimplifyTerm(write[1]);
+ ASTNode writeVal = SimplifyTerm(write[2]);
+
+ //compare the readIndex and the current writeIndex and see if they
+ //simplify to TRUE or FALSE or UNDETERMINABLE at this stage
+ ASTNode compare_readwrite_indices =
+ SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
+
+ //if readIndex and writeIndex are equal
+ if(ASTTrue == compare_readwrite_indices && !SeenNonConstWriteIndex) {
+ UpdateSimplifyMap(term,writeVal,false);
+ return writeVal;
+ }
+
+ if(!(ASTTrue == compare_readwrite_indices ||
+ ASTFalse == compare_readwrite_indices)) {
+ SeenNonConstWriteIndex = true;
+ }
+
+ //if (readIndex=writeIndex <=> FALSE)
+ if(ASTFalse == compare_readwrite_indices
+ ||
+ (WriteIndicesSeenSoFar.find(writeIndex) != WriteIndicesSeenSoFar.end())
+ ) {
+ //drop the current level write
+ //do nothing
+ }
+ else {
+ writeIndices.push_back(writeIndex);
+ writeValues.push_back(writeVal);
+ }
+
+ //record the write indices seen so far
+ //if(BVCONST == writeIndex.GetKind()) {
+ WriteIndicesSeenSoFar.insert(writeIndex);
+ //}
+
+ //Setup the write for the new iteration, one level inner write
+ write = write[0];
+ }while (SYMBOL != write.GetKind());
+
+ ASTVec::reverse_iterator it_index = writeIndices.rbegin();
+ ASTVec::reverse_iterator itend_index = writeIndices.rend();
+ ASTVec::reverse_iterator it_values = writeValues.rbegin();
+ ASTVec::reverse_iterator itend_values = writeValues.rend();
+
+ //"write" must be a symbol at the control point before the
+ //begining of the "for loop"
+
+ for(;it_index!=itend_index;it_index++,it_values++) {
+ write = CreateTerm(WRITE,width,write,*it_index,*it_values);
+ write.SetIndexWidth(indexwidth);
+ }
+
+ output = CreateTerm(READ,width,write,readIndex);
+ UpdateSimplifyMap(term,output,false);
+ return output;
+ } //end of SimplifyWrites_In_Place()
+
+ //accepts a read over a write and returns a term without the write
+ //READ(WRITE(A i val) j) <==> ITE(i=j,val,READ(A,j)). We use a memo
+ //table for this function called RemoveWritesMemoMap
+ ASTNode BeevMgr::RemoveWrites(const ASTNode& input) {
+ //unsigned int width = input.GetValueWidth();
+ if(READ != input.GetKind() || WRITE != input[0].GetKind()) {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE",input);
+ }
+
+ ASTNodeMap::iterator it;
+ ASTNode output = input;
+ if(CheckSimplifyMap(input,output,false)) {
+ return output;
+ }
+
+ if(!start_abstracting && Begin_RemoveWrites) {
+ output= ReadOverWrite_To_ITE(input);
+ }
+
+ if(start_abstracting) {
+ ASTNode newVar;
+ if(!CheckSimplifyMap(input,newVar,false)) {
+ newVar = NewVar(input.GetValueWidth());
+ ReadOverWrite_NewName_Map[input] = newVar;
+ NewName_ReadOverWrite_Map[newVar] = input;
+
+ UpdateSimplifyMap(input,newVar,false);
+ ASTNodeStats("New Var Name which replace Read_Over_Write: ", newVar);
+ }
+ output = newVar;
+ } //end of start_abstracting if condition
+
+ //memoize
+ UpdateSimplifyMap(input,output,false);
+ return output;
+ } //end of RemoveWrites()
+
+ ASTNode BeevMgr::ReadOverWrite_To_ITE(const ASTNode& term) {
+ unsigned int width = term.GetValueWidth();
+ ASTNode input = term;
+ if(READ != term.GetKind() || WRITE != term[0].GetKind()) {
+ FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+ }
+
+ ASTNodeMap::iterator it;
+ ASTNode output;
+ // if(CheckSimplifyMap(term,output,false)) {
+ // return output;
+ // }
+
+ ASTNode partialITE = term;
+ ASTNode writeA = ASTTrue;
+ ASTNode oldRead = term;
+ //iteratively expand read-over-write
+ do {
+ ASTNode write = input[0];
+ ASTNode readIndex = SimplifyTerm(input[1]);
+ //DO NOT CALL SimplifyTerm() on write[0]. You will go into an
+ //infinite loop
+ writeA = write[0];
+ ASTNode writeIndex = SimplifyTerm(write[1]);
+ ASTNode writeVal = SimplifyTerm(write[2]);
+
+ ASTNode cond = SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
+ ASTNode newRead = CreateTerm(READ,width,writeA,readIndex);
+ ASTNode newRead_memoized = newRead;
+ if(CheckSimplifyMap(newRead, newRead_memoized,false)) {
+ newRead = newRead_memoized;
+ }
+
+ if(ASTTrue == cond && (term == partialITE)) {
+ //found the write-value in the first iteration itself. return
+ //it
+ output = writeVal;
+ UpdateSimplifyMap(term,output,false);
+ return output;
+ }
+
+ if(READ == partialITE.GetKind() && WRITE == partialITE[0].GetKind()) {
+ //first iteration or (previous cond==ASTFALSE and partialITE is a "READ over WRITE")
+ partialITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
+ }
+ else if (ITE == partialITE.GetKind()){
+ //ITE(i1 = j, v1, R(A,j))
+ ASTNode ElseITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
+ //R(W(A,i1,v1),j) <==> ITE(i1 = j, v1, R(A,j))
+ UpdateSimplifyMap(oldRead,ElseITE,false);
+ //ITE(i2 = j, v2, R(W(A,i1,v1),j)) <==> ITE(i2 = j, v2, ITE(i1 = j, v1, R(A,j)))
+ partialITE = SimplifyTerm(partialITE);
+ }
+ else {
+ FatalError("RemoveWrites: Control should not reach here\n");
+ }
+
+ if(ASTTrue == cond) {
+ //no more iterations required
+ output = partialITE;
+ UpdateSimplifyMap(term,output,false);
+ return output;
+ }
+
+ input = newRead;
+ oldRead = newRead;
+ } while(READ == input.GetKind() && WRITE == input[0].GetKind());
+
+ output = partialITE;
+
+ //memoize
+ //UpdateSimplifyMap(term,output,false);
+ return output;
+ } //ReadOverWrite_To_ITE()
+
+ //compute the multiplicative inverse of the input
+ ASTNode BeevMgr::MultiplicativeInverse(const ASTNode& d) {
+ ASTNode c = d;
+ if(BVCONST != c.GetKind()) {
+ FatalError("Input must be a constant", c);
+ }
+
+ if(!BVConstIsOdd(c)) {
+ FatalError("MultiplicativeInverse: Input must be odd: ",c);
+ }
+
+ //cerr << "input to multinverse function is: " << d << endl;
+ ASTNode inverse;
+ if(CheckMultInverseMap(d,inverse)) {
+ //cerr << "found the inverse of: " << d << "and it is: " << inverse << endl;
+ return inverse;
+ }
+
+ inverse = c;
+ unsigned inputwidth = c.GetValueWidth();
+
+#ifdef NATIVE_C_ARITH
+ ASTNode one = CreateOneConst(inputwidth);
+ while(c != one) {
+ //c = c*c
+ c = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,c,c));
+ //inverse = invsere*c
+ inverse = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,inverse,c));
+ }
+#else
+ //Compute the multiplicative inverse of c using the extended
+ //euclidian algorithm
+ //
+ //create a '0' which is 1 bit long
+ ASTNode onebit_zero = CreateZeroConst(1);
+ //zero pad t0, i.e. 0 @ t0
+ c = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,c));
+
+ //construct 2^(inputwidth), i.e. a bitvector of length
+ //'inputwidth+1', which is max(inputwidth)+1
+ //
+ //all 1's
+ ASTNode max = CreateMaxConst(inputwidth);
+ //zero pad max
+ max = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,max));
+ //Create a '1' which has leading zeros of length 'inputwidth'
+ ASTNode inputwidthplusone_one = CreateOneConst(inputwidth+1);
+ //add 1 to max
+ max = CreateTerm(BVPLUS,inputwidth+1,max,inputwidthplusone_one);
+ max = BVConstEvaluator(max);
+
+ ASTNode zero = CreateZeroConst(inputwidth+1);
+ ASTNode max_bvgt_0 = CreateNode(BVGT,max,zero);
+ ASTNode quotient, remainder;
+ ASTNode x, x1, x2;
+
+ //x1 initialized to zero
+ x1 = zero;
+ //x2 initialized to one
+ x2 = CreateOneConst(inputwidth+1);
+ while (ASTTrue == BVConstEvaluator(max_bvgt_0)) {
+ //quotient = (c divided by max)
+ quotient = BVConstEvaluator(CreateTerm(BVDIV,inputwidth+1, c, max));
+
+ //remainder of (c divided by max)
+ remainder = BVConstEvaluator(CreateTerm(BVMOD,inputwidth+1, c, max));
+
+ //x = x2 - q*x1
+ x = CreateTerm(BVSUB,inputwidth+1,x2,CreateTerm(BVMULT,inputwidth+1,quotient,x1));
+ x = BVConstEvaluator(x);
+
+ //fix the inputs to the extended euclidian algo
+ c = max;
+ max = remainder;
+ max_bvgt_0 = CreateNode(BVGT,max,zero);
+
+ x2 = x1;
+ x1 = x;
+ }
+
+ ASTNode hi = CreateBVConst(32,inputwidth-1);
+ ASTNode low = CreateZeroConst(32);
+ inverse = CreateTerm(BVEXTRACT,inputwidth,x2,hi,low);
+ inverse = BVConstEvaluator(inverse);
+#endif
+
+ UpdateMultInverseMap(d,inverse);
+ //cerr << "output of multinverse function is: " << inverse << endl;
+ return inverse;
+ } //end of MultiplicativeInverse()
+
+ //returns true if the input is odd
+ bool BeevMgr::BVConstIsOdd(const ASTNode& c) {
+ if(BVCONST != c.GetKind()) {
+ FatalError("Input must be a constant", c);
+ }
+
+ ASTNode zero = CreateZeroConst(1);
+ ASTNode hi = CreateZeroConst(32);
+ ASTNode low = hi;
+ ASTNode lowestbit = CreateTerm(BVEXTRACT,1,c,hi,low);
+ lowestbit = BVConstEvaluator(lowestbit);
+
+ if(lowestbit == zero) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ } //end of BVConstIsOdd()
+
+ //The big substitution function
+ ASTNode BeevMgr::CreateSubstitutionMap(const ASTNode& a){
+ if(!optimize)
+ return a;
+
+ ASTNode output = a;
+ //if the variable has been solved for, then simply return it
+ if(CheckSolverMap(a,output))
+ return output;
+
+ //traverse a and populate the SubstitutionMap
+ Kind k = a.GetKind();
+ if(SYMBOL == k && BOOLEAN_TYPE == a.GetType()) {
+ bool updated = UpdateSubstitutionMap(a,ASTTrue);
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+ if(NOT == k
+ && SYMBOL == a[0].GetKind()) {
+ bool updated = UpdateSubstitutionMap(a[0],ASTFalse);
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+
+ if(IFF == k) {
+ ASTVec c = a.GetChildren();
+ SortByExprNum(c);
+ if(SYMBOL != c[0].GetKind() ||
+ VarSeenInTerm(c[0],SimplifyFormula_NoRemoveWrites(c[1],false))) {
+ return a;
+ }
+ bool updated = UpdateSubstitutionMap(c[0],c[1]);
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+
+ if(EQ == k) {
+ //fill the arrayname readindices vector if e0 is a
+ //READ(Arr,index) and index is a BVCONST
+ ASTVec c = a.GetChildren();
+ SortByExprNum(c);
+ FillUp_ArrReadIndex_Vec(c[0],c[1]);
+
+ if(SYMBOL == c[0].GetKind() &&
+ VarSeenInTerm(c[0],SimplifyTerm(c[1]))) {
+ return a;
+ }
+
+ if(1 == TermOrder(c[0],c[1]) &&
+ READ == c[0].GetKind() &&
+ VarSeenInTerm(c[0][0],SimplifyTerm(c[1]))) {
+ return a;
+ }
+ bool updated = UpdateSubstitutionMap(c[0],c[1]);
+ output = updated ? ASTTrue : a;
+ return output;
+ }
+
+ if(AND == k){
+ ASTVec o;
+ ASTVec c = a.GetChildren();
+ for(ASTVec::iterator it = c.begin(),itend=c.end();it!=itend;it++) {
+ UpdateAlwaysTrueFormMap(*it);
+ ASTNode aaa = CreateSubstitutionMap(*it);
+
+ if(ASTTrue != aaa) {
+ if(ASTFalse == aaa)
+ return ASTFalse;
+ else
+ o.push_back(aaa);
+ }
+ }
+ if(o.size() == 0)
+ return ASTTrue;
+
+ if(o.size() == 1)
+ return o[0];
+
+ return CreateNode(AND,o);
+ }
+ return output;
+ } //end of CreateSubstitutionMap()
+
+
+ bool BeevMgr::VarSeenInTerm(const ASTNode& var, const ASTNode& term) {
+ if(READ == term.GetKind() &&
+ WRITE == term[0].GetKind() && !Begin_RemoveWrites) {
+ return false;
+ }
+
+ if(READ == term.GetKind() &&
+ WRITE == term[0].GetKind() && Begin_RemoveWrites) {
+ return true;
+ }
+
+ ASTNodeMap::iterator it;
+ if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
+ if(it->second == var) {
+ return false;
+ }
+ }
+
+ if(var == term) {
+ return true;
+ }
+
+ for(ASTVec::const_iterator it=term.begin(),itend=term.end();it!=itend;it++){
+ if(VarSeenInTerm(var,*it)) {
+ return true;
+ }
+ else {
+ TermsAlreadySeenMap[*it] = var;
+ }
+ }
+
+ TermsAlreadySeenMap[term] = var;
+ return false;
+ }
+};//end of namespace
Added: klee/trunk/test/CXX/ArrayNew.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/ArrayNew.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/ArrayNew.cpp (added)
+++ klee/trunk/test/CXX/ArrayNew.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,38 @@
+// RUN: %llvmgxx %s --emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --no-output --exit-on-error --no-externals %t1.bc
+
+#include <cassert>
+
+static int decon = 0;
+
+class Test {
+ int x;
+
+public:
+ Test() {}
+ Test(int _x) : x(_x) { }
+ ~Test() { decon += x; }
+
+ int getX() { return x; }
+ void setX(int _x) { x = _x; }
+};
+
+int main(int argc) {
+ Test *rt = new Test[4];
+ int i;
+
+ for (i=0; i<4; i++)
+ rt[i].setX(i+1);
+
+ int sum = 0;
+ for (i=0; i<4; i++)
+ sum += rt[i].getX();
+
+ assert(sum==10);
+
+ delete[] rt;
+
+ assert(decon==10);
+
+ return 0;
+}
Added: klee/trunk/test/CXX/New.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/New.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/New.cpp (added)
+++ klee/trunk/test/CXX/New.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,29 @@
+// RUN: %llvmgxx %s --emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --no-output --exit-on-error --no-externals %t1.bc
+
+#include <cassert>
+
+class Test {
+ int x;
+
+public:
+ Test(int _x) : x(_x) {
+ }
+ ~Test() {
+ }
+
+ int getX() { return x; }
+};
+
+// This doesn't do what I want because
+// it is being changed to alloca, but
+// it is also failing.
+int main(int argc) {
+ Test *rt = new Test(2);
+
+ assert(rt->getX()==2);
+
+ delete rt;
+
+ return 0;
+}
Added: klee/trunk/test/CXX/SimpleVirtual.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/SimpleVirtual.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/SimpleVirtual.cpp (added)
+++ klee/trunk/test/CXX/SimpleVirtual.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,38 @@
+// RUN: %llvmgxx %s --emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --no-output --exit-on-error --no-externals %t1.bc
+
+#include <cassert>
+
+static int decon = 0;
+
+class Thing {
+public:
+ Thing() {}
+ virtual ~Thing() { decon += getX(); }
+
+ virtual int getX() { return 1; };
+};
+
+class Thing2 : public Thing {
+public:
+ virtual int getX() { return 2; };
+};
+
+Thing *getThing(bool which) {
+ return which ? new Thing() : new Thing2();
+}
+
+int main(int argc) {
+ Thing *one = getThing(false);
+ Thing *two = getThing(true);
+
+ int x = one->getX() + two->getX();
+ assert(x==3);
+
+ delete two;
+ delete one;
+
+ assert(decon==2);
+
+ return 0;
+}
Added: klee/trunk/test/CXX/StaticConstructor.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/StaticConstructor.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/StaticConstructor.cpp (added)
+++ klee/trunk/test/CXX/StaticConstructor.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,25 @@
+// RUN: %llvmgxx %s --emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --libc=klee --no-output --exit-on-error %t1.bc
+
+#include <cassert>
+
+// to make sure globals are initialized
+int aGlobal = 21;
+
+class Test {
+ int x;
+
+public:
+ Test() : x(aGlobal + 1) {}
+ ~Test() {}
+
+ int getX() { return x; }
+};
+
+Test t;
+
+int main() {
+ assert(t.getX()==22);
+
+ return 0;
+}
Added: klee/trunk/test/CXX/StaticDestructor.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/StaticDestructor.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/StaticDestructor.cpp (added)
+++ klee/trunk/test/CXX/StaticDestructor.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,24 @@
+// don't optimize this, llvm likes to turn the *p into unreachable
+
+// RUN: %llvmgxx %s --emit-llvm -g -O0 -c -o %t1.bc
+// RUN: %klee --libc=klee --no-output %t1.bc 2> %t1.log
+// RUN: grep ":16: memory error" %t1.log
+
+#include <cassert>
+
+class Test {
+ int *p;
+
+public:
+ Test() : p(0) {}
+ ~Test() {
+ assert(!p);
+ assert(*p == 10); // crash here
+ }
+};
+
+Test t;
+
+int main() {
+ return 0;
+}
Added: klee/trunk/test/CXX/Trivial.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/Trivial.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/Trivial.cpp (added)
+++ klee/trunk/test/CXX/Trivial.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+// RUN: %llvmgxx %s --emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --no-output --exit-on-error %t1.bc
+
+#include <cassert>
+
+class Test {
+ int x;
+
+public:
+ Test(int _x) : x(_x) {}
+ ~Test() {}
+
+ int getX() { return x; }
+};
+
+int main() {
+ Test rt(2);
+
+ assert(rt.getX()==2);
+
+ return 0;
+}
Added: klee/trunk/test/CXX/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/CXX/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/CXX/dg.exp (added)
+++ klee/trunk/test/CXX/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
Added: klee/trunk/test/Concrete/BitwiseOps.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/BitwiseOps.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/BitwiseOps.ll (added)
+++ klee/trunk/test/Concrete/BitwiseOps.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+ %a = or i32 12345678, 87654321
+ %b = and i32 %a, 87654321
+ %check = xor i32 %b, 87654321
+ %test = icmp eq i32 %check, 0
+ br i1 %test, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/BoolReadWrite.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/BoolReadWrite.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/BoolReadWrite.ll (added)
+++ klee/trunk/test/Concrete/BoolReadWrite.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,13 @@
+declare void @print_i1(i1)
+
+define i32 @main() {
+ %mem = alloca i1
+ store i1 1, i1* %mem
+ %v = load i1* %mem
+ br i1 %v, label %ok, label %exit
+ok:
+ call void @print_i1(i1 %v)
+ br label %exit
+exit:
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/Casts.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/Casts.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/Casts.ll (added)
+++ klee/trunk/test/Concrete/Casts.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+ %a = add i32 315904, 128
+ %b = trunc i32 %a to i8
+ %c0 = icmp eq i8 %b, 128
+ %d = zext i8 %b to i32
+ %c1 = icmp eq i32 %d, 128
+ %e = sext i8 %b to i32
+ %c2 = icmp eq i32 %e, -128
+ %c0i = zext i1 %c0 to i32
+ %c1i = zext i1 %c1 to i32
+ %c2i = zext i1 %c2 to i32
+ %c0is = shl i32 %c0i, 0
+ %c1is = shl i32 %c1i, 1
+ %c2is = shl i32 %c2i, 2
+ %tmp = add i32 %c0is, %c1is
+ %res = add i32 %tmp, %c2is
+ %p = icmp eq i32 %res, 7
+ br i1 %p, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Propchange: klee/trunk/test/Concrete/Casts.ll
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/test/Concrete/CmpEq.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/CmpEq.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/CmpEq.ll (added)
+++ klee/trunk/test/Concrete/CmpEq.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,14 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+ %a = add i8 0, 1
+ %b = add i8 %a, -1
+ %c = icmp eq i8 %b, 0
+ br i1 %c, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/ConcreteTest.py
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/ConcreteTest.py?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/ConcreteTest.py (added)
+++ klee/trunk/test/Concrete/ConcreteTest.py Wed May 20 23:36:41 2009
@@ -0,0 +1,99 @@
+#!/usr/bin/python
+
+import os
+import sys
+import popen2
+
+class TestError(Exception):
+ pass
+
+kLLIPath = '../../llvm/Debug/bin/lli'
+kKleePath = '../../Debug/bin/klee'
+
+def getFiles():
+ for name in os.listdir('.'):
+ if (name[0]!='.' and name[0]!='_' and
+ (name.endswith('.ll') or name.endswith('.c'))):
+ yield name
+
+def readFile(f):
+ s = ""
+ while 1:
+ data = f.read()
+ if not data:
+ break
+ s += data
+ return s
+
+def testFile(name, printOutput=False):
+ baseName,ext = os.path.splitext(name)
+ exeFile = 'Output/linked_%s.bc'%baseName
+ if printOutput:
+ redirectStderr = ''
+ else:
+ redirectStderr = '2> /dev/null'
+
+ if os.system('make %s > /dev/null %s'%(exeFile,redirectStderr)):
+ raise TestError('make failed')
+
+ if printOutput:
+ print '-- running lli --'
+ lli = popen2.Popen3('%s -force-interpreter=true %s %s'%(kLLIPath,exeFile,redirectStderr))
+ lliOut = readFile(lli.fromchild)
+ if lli.wait():
+ raise TestError('lli execution failed')
+
+ if printOutput:
+ print lliOut
+
+ if printOutput:
+ print '-- running klee --'
+ klee = popen2.Popen3('%s --no-output %s %s'%(kKleePath,exeFile,redirectStderr))
+ kleeOut = readFile(klee.fromchild)
+ if klee.wait():
+ raise TestError('klee execution failed')
+ if printOutput:
+ print kleeOut
+
+ if lliOut!=kleeOut:
+ raise TestError('outputs differ')
+
+def testOneFile(f, printOutput=False, log=None):
+ try:
+ testFile(f, printOutput)
+ code = ['pass','xpass'][f.startswith('broken')]
+ extra = ''
+ except TestError,e:
+ code = ['fail','xfail'][f.startswith('broken')]
+ extra = str(e)
+
+ print '%s: %s -- %s'%(code,f,extra)
+ if log:
+ print >>log,'%s: %s -- %s'%(code,f,extra)
+
+def test():
+ if not os.path.exists('Output'):
+ os.mkdir('Output')
+ log = open("Output/test.log","w")
+ files = list(getFiles())
+ files.sort(key = lambda n: n.lower())
+ for f in files:
+ testOneFile(f, log=log)
+ log.close()
+
+if __name__=='__main__':
+ args = sys.argv
+ args.pop(0)
+
+ runAll = not args
+
+ while args:
+ arg = args.pop(0)
+ if arg=='--run':
+ testFile(args.pop(0), printOutput=True)
+ else:
+ raise ValueError,'invalid argument: %s'%arg
+
+ if runAll:
+ test()
+
Propchange: klee/trunk/test/Concrete/ConcreteTest.py
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/test/Concrete/ConstantExpr.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/ConstantExpr.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/ConstantExpr.ll (added)
+++ klee/trunk/test/Concrete/ConstantExpr.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,166 @@
+ at gInt = global i32 10
+ at gIntWithConstant = global i32 sub(i32 ptrtoint(i32* @gInt to i32),
+ i32 ptrtoint(i32* @gInt to i32))
+
+define void @"test_int_to_ptr"()
+begin
+ %t1 = add i8 ptrtoint(i8* inttoptr(i32 100 to i8*) to i8), 0
+ %t2 = add i32 ptrtoint(i32* inttoptr(i8 100 to i32*) to i32), 0
+ %t3 = add i32 ptrtoint(i32* inttoptr(i64 100 to i32*) to i32), 0
+ %t4 = add i64 ptrtoint(i8* inttoptr(i32 100 to i8*) to i64), 0
+
+ call void @print_i8(i8 %t1)
+ call void @print_i32(i32 %t2)
+ call void @print_i32(i32 %t3)
+ call void @print_i64(i64 %t4)
+
+ ret void
+end
+
+define void @"test_constant_ops"()
+begin
+ %t1 = add i8 trunc(i64 add(i64 ptrtoint(i32* @gInt to i64), i64 -10) to i8), 10
+ %t2 = sub i64 sext(i32 ptrtoint(i32* @gInt to i32) to i64), ptrtoint(i32* @gInt to i64)
+ %t3 = sub i64 zext(i32 ptrtoint(i32* @gInt to i32) to i64), ptrtoint(i32* @gInt to i64)
+
+ %t4 = icmp eq i8 trunc(i64 ptrtoint(i32* @gInt to i64) to i8), %t1
+ %t5 = zext i1 %t4 to i8
+
+ call void @print_i8(i8 %t5)
+ call void @print_i64(i64 %t2)
+ call void @print_i64(i64 %t3)
+
+ ret void
+end
+
+define void @"test_logical_ops"()
+begin
+ %t1 = add i32 -10, and(i32 ptrtoint(i32* @gInt to i32), i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 -1))
+ %t2 = add i32 -10, or(i32 ptrtoint(i32* @gInt to i32), i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 -1))
+ %t3 = add i32 -10, xor(i32 xor(i32 ptrtoint(i32* @gInt to i32), i32 1024), i32 ptrtoint(i32* @gInt to i32))
+
+ call void @print_i32(i32 %t1)
+ call void @print_i32(i32 %t2)
+ call void @print_i32(i32 %t3)
+
+ %t4 = shl i32 lshr(i32 ptrtoint(i32* @gInt to i32), i32 8), 8
+ %t5 = shl i32 ashr(i32 ptrtoint(i32* @gInt to i32), i32 8), 8
+ %t6 = lshr i32 shl(i32 ptrtoint(i32* @gInt to i32), i32 8), 8
+
+ %t7 = icmp eq i32 %t4, %t5
+ %t8 = icmp ne i32 %t4, %t6
+
+ %t9 = zext i1 %t7 to i8
+ %t10 = zext i1 %t8 to i8
+
+ call void @print_i8(i8 %t9)
+ call void @print_i8(i8 %t10)
+
+ ret void
+end
+
+%test.struct.type = type { i32, i32 }
+ at test_struct = global %test.struct.type { i32 0, i32 10 }
+
+define void @"test_misc"()
+begin
+ ; probability that @gInt == 100 is very very low
+ %t1 = add i32 select(i1 icmp eq (i32* @gInt, i32* inttoptr(i32 100 to i32*)), i32 10, i32 0), 0
+ call void @print_i32(i32 %t1)
+
+ %t2 = load i32* getelementptr(%test.struct.type* @test_struct, i32 0, i32 1)
+ call void @print_i32(i32 %t2)
+
+ ret void
+end
+
+define void @"test_simple_arith"()
+begin
+ %t1 = add i32 add(i32 ptrtoint(i32* @gInt to i32), i32 0), 0
+ %t2 = add i32 sub(i32 0, i32 ptrtoint(i32* @gInt to i32)), %t1
+ %t3 = mul i32 mul(i32 ptrtoint(i32* @gInt to i32), i32 10), %t2
+
+ call void @print_i32(i32 %t3)
+
+ ret void
+end
+
+define void @"test_div_and_mod"()
+begin
+ %t1 = add i32 udiv(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+ %t2 = add i32 urem(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+ %t3 = add i32 sdiv(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+ %t4 = add i32 srem(i32 ptrtoint(i32* @gInt to i32), i32 13), 0
+
+ %p = ptrtoint i32* @gInt to i32
+
+ %i1 = udiv i32 %p, 13
+ %i2 = urem i32 %p, 13
+ %i3 = sdiv i32 %p, 13
+ %i4 = srem i32 %p, 13
+
+ %x1 = sub i32 %t1, %i1
+ %x2 = sub i32 %t2, %i2
+ %x3 = sub i32 %t3, %i3
+ %x4 = sub i32 %t4, %i4
+
+ call void @print_i32(i32 %x1)
+ call void @print_i32(i32 %x2)
+ call void @print_i32(i32 %x3)
+ call void @print_i32(i32 %x4)
+
+ ret void
+end
+
+define void @test_cmp()
+begin
+ %t1 = add i8 zext(i1 icmp ult (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t2 = add i8 zext(i1 icmp ule (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t3 = add i8 zext(i1 icmp uge (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t4 = add i8 zext(i1 icmp ugt (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t5 = add i8 zext(i1 icmp slt (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t6 = add i8 zext(i1 icmp sle (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t7 = add i8 zext(i1 icmp sge (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t8 = add i8 zext(i1 icmp sgt (i32 ptrtoint(i32* @gInt to i32), i32 0) to i8), 1
+ %t9 = add i8 zext(i1 icmp eq (i32 ptrtoint(i32* @gInt to i32), i32 10) to i8), 1
+ %t10 = add i8 zext(i1 icmp ne (i32 ptrtoint(i32* @gInt to i32), i32 10) to i8), 1
+
+ call void @print_i1(i8 %t1)
+ call void @print_i1(i8 %t2)
+ call void @print_i1(i8 %t3)
+ call void @print_i1(i8 %t4)
+ call void @print_i1(i8 %t5)
+ call void @print_i1(i8 %t6)
+ call void @print_i1(i8 %t7)
+ call void @print_i1(i8 %t8)
+ call void @print_i1(i8 %t9)
+ call void @print_i1(i8 %t10)
+
+ ret void
+end
+
+define i32 @main()
+begin
+ call void @test_simple_arith()
+
+ call void @test_div_and_mod()
+
+ call void @test_cmp()
+
+ call void @test_int_to_ptr()
+
+ call void @test_constant_ops()
+
+ call void @test_logical_ops()
+
+ call void @test_misc()
+
+ ret i32 0
+end
+
+; defined in print_int.c
+declare void @print_i1(i8)
+declare void @print_i8(i8)
+declare void @print_i16(i16)
+declare void @print_i32(i32)
+declare void @print_i64(i64)
Added: klee/trunk/test/Concrete/FloatingPointOps.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/FloatingPointOps.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/FloatingPointOps.ll (added)
+++ klee/trunk/test/Concrete/FloatingPointOps.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,685 @@
+%struct.stdout = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.stdout*, i32, i32, i32, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i32, i32, [40 x i8] }
+%struct._IO_marker = type { %struct._IO_marker*, %struct.stdout*, i32 }
+ at stdout = external global %struct.stdout*
+
+; casting error messages
+ at .strTrunc = internal constant [15 x i8] c"FPTrunc broken\00"
+ at .strExt = internal constant [13 x i8] c"FPExt broken\00"
+ at .strFPToUIFlt = internal constant [20 x i8] c"FPToUI float broken\00"
+ at .strFPToUIDbl = internal constant [21 x i8] c"FPToUI double broken\00"
+ at .strFPToSIFlt = internal constant [20 x i8] c"FPToSI float broken\00"
+ at .strFPToSIDbl = internal constant [21 x i8] c"FPToSI double broken\00"
+ at .strUIToFPFlt = internal constant [20 x i8] c"UIToFP float broken\00"
+ at .strUIToFPDbl = internal constant [21 x i8] c"UIToFP double broken\00"
+ at .strSIToFPFlt = internal constant [20 x i8] c"SIToFP float broken\00"
+ at .strSIToFPDbl = internal constant [21 x i8] c"SIToFP double broken\00"
+
+; mathematical operator error messages
+ at .strDivFlt = internal constant [18 x i8] c"FDiv float broken\00"
+ at .strDivDbl = internal constant [19 x i8] c"FDiv double broken\00"
+ at .strRemFlt = internal constant [18 x i8] c"FRem float broken\00"
+ at .strRemDbl = internal constant [19 x i8] c"FRem double broken\00"
+ at .strAddInt = internal constant [16 x i8] c"Add ints broken\00"
+ at .strAddFlt = internal constant [18 x i8] c"Add floats broken\00"
+ at .strAddDbl = internal constant [19 x i8] c"Add doubles broken\00"
+ at .strSubInt = internal constant [16 x i8] c"Sub ints broken\00"
+ at .strSubFlt = internal constant [18 x i8] c"Sub floats broken\00"
+ at .strSubDbl = internal constant [19 x i8] c"Sub doubles broken\00"
+ at .strMulInt = internal constant [16 x i8] c"Mul ints broken\00"
+ at .strMulFlt = internal constant [18 x i8] c"Mul floats broken\00"
+ at .strMulDbl = internal constant [19 x i8] c"Mul doubles broken\00"
+
+; fcmp error messages
+ at .strCmpTrFlt = internal constant [19 x i8] c"floats TRUE broken\00" ; fcmp::generic broken msgs
+ at .strCmpFaFlt = internal constant [20 x i8] c"floats FALSE broken\00"
+ at .strCmpTrDbl = internal constant [19 x i8] c"double TRUE broken\00"
+ at .strCmpFaDbl = internal constant [20 x i8] c"double FALSE broken\00"
+ at .strCmpEqFlt = internal constant [17 x i8] c"floats == broken\00" ; fcmp::ordered broken msgs
+ at .strCmpGeFlt = internal constant [17 x i8] c"floats >= broken\00"
+ at .strCmpGtFlt = internal constant [17 x i8] c"floats > broken\00"
+ at .strCmpLeFlt = internal constant [17 x i8] c"floats <= broken\00"
+ at .strCmpLtFlt = internal constant [17 x i8] c"floats < broken\00"
+ at .strCmpNeFlt = internal constant [17 x i8] c"floats != broken\00"
+ at .strCmpOrdFlt = internal constant [18 x i8] c"floats ORD broken\00"
+ at .strCmpEqDbl = internal constant [18 x i8] c"doubles == broken\00"
+ at .strCmpGeDbl = internal constant [18 x i8] c"doubles >= broken\00"
+ at .strCmpGtDbl = internal constant [18 x i8] c"doubles > broken\00"
+ at .strCmpLeDbl = internal constant [18 x i8] c"doubles <= broken\00"
+ at .strCmpLtDbl = internal constant [18 x i8] c"doubles < broken\00"
+ at .strCmpNeDbl = internal constant [18 x i8] c"doubles != broken\00"
+ at .strCmpOrdDbl = internal constant [19 x i8] c"doubles ORD broken\00"
+ at .strCmpEqFltU = internal constant [17 x i8] c"U:floats==broken\00" ; fcmp::unordered broken msgs
+ at .strCmpGeFltU = internal constant [17 x i8] c"U:floats>=broken\00"
+ at .strCmpGtFltU = internal constant [17 x i8] c"U:floats> broken\00"
+ at .strCmpLeFltU = internal constant [17 x i8] c"U:floats<=broken\00"
+ at .strCmpLtFltU = internal constant [17 x i8] c"U:floats< broken\00"
+ at .strCmpNeFltU = internal constant [17 x i8] c"U:floats!=broken\00"
+ at .strCmpUnoFlt = internal constant [20 x i8] c"U:floats UNO broken\00"
+ at .strCmpEqDblU = internal constant [18 x i8] c"U:doubles==broken\00"
+ at .strCmpGeDblU = internal constant [18 x i8] c"U:doubles>=broken\00"
+ at .strCmpGtDblU = internal constant [18 x i8] c"U:doubles> broken\00"
+ at .strCmpLeDblU = internal constant [18 x i8] c"U:doubles<=broken\00"
+ at .strCmpLtDblU = internal constant [18 x i8] c"U:doubles< broken\00"
+ at .strCmpNeDblU = internal constant [18 x i8] c"U:doubles!=broken\00"
+ at .strCmpUnoDbl = internal constant [21 x i8] c"U:doubles UNO broken\00"
+
+ at .strWorks = internal constant [20 x i8] c"Everything works!\0D\0A\00"
+ at .strNL = internal constant [3 x i8] c"\0D\0A\00"
+
+declare i32 @fprintf(%struct.stdout*, i8*, ...)
+declare void @exit(i32)
+declare void @llvm.memcpy.i32(i8*, i8*, i32, i32)
+
+; if isOk is false, then print errMsg to stdout and exit(1)
+define void @failCheck(i1 %isOk, i8* %errMsg) {
+entry:
+ %fail = icmp eq i1 %isOk, 0
+ br i1 %fail, label %failed, label %return
+
+failed:
+ ; print the error msg
+ %err_stream = load %struct.stdout** @stdout
+ %ret = call i32 (%struct.stdout*, i8*, ...)* @fprintf( %struct.stdout* %err_stream, i8* %errMsg )
+
+ ; add a newline to the ostream
+ %nl = getelementptr [3 x i8]* @.strNL, i32 0, i32 0
+ %ret2 = call i32 (%struct.stdout*, i8*, ...)* @fprintf( %struct.stdout* %err_stream, i8* %nl )
+
+ ; exit with return value 1 to denote that an error occurred
+ call void @exit( i32 1 )
+ unreachable
+
+return:
+ ret void
+}
+
+; test FPTrunc which casts doubles to floats
+define void @testFPTrunc() {
+entry:
+ %d_addr = alloca double, align 8
+ store double 8.000000e+00, double* %d_addr
+ %d = load double* %d_addr
+ %f = fptrunc double %d to float
+ %matches = fcmp oeq float %f, 8.000000e+00
+ %err_msg = getelementptr [15 x i8]* @.strTrunc, i32 0, i32 0
+ call void @failCheck( i1 %matches, i8* %err_msg )
+ ret void
+}
+
+; test FPExt which casts floats to doubles
+define void @testFPExt() {
+entry:
+ %f_addr = alloca float, align 4
+ store float 8.000000e+00, float* %f_addr
+ %f = load float* %f_addr
+ %d = fpext float %f to double
+ %matches = fcmp oeq double %d, 8.000000e+00
+ %err_msg = getelementptr [13 x i8]* @.strExt, i32 0, i32 0
+ call void @failCheck( i1 %matches, i8* %err_msg )
+ ret void
+}
+
+; test casting fp to an unsigned int
+define void @testFPToUI() {
+entry:
+ %f_addr = alloca float, align 4
+ %d_addr = alloca double, align 8
+
+ ; test float to UI
+ store float 0x4020333340000000, float* %f_addr; %f = 8.1
+ %f = load float* %f_addr
+ %uf = fptoui float %f to i32
+ %matchesf = icmp eq i32 %uf, 8
+ %err_msgf = getelementptr [20 x i8]* @.strFPToUIFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; test double to UI
+ store double 8.100000e+00, double* %d_addr
+ %d = load double* %d_addr
+ %ud = fptoui double %d to i32
+ %matchesd = icmp eq i32 %ud, 8
+ %err_msgd = getelementptr [21 x i8]* @.strFPToUIDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test casting fp to a signed int
+define void @testFPToSI() {
+entry:
+ %f_addr = alloca float, align 4
+ %d_addr = alloca double, align 8
+
+ ; test float 8.1 to signed int
+ store float 0x4020333340000000, float* %f_addr
+ %f = load float* %f_addr
+ %sf = fptosi float %f to i32
+ %matchesf = icmp eq i32 %sf, 8
+ %err_msgf = getelementptr [20 x i8]* @.strFPToSIFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; test double -8.1 to signed int
+ store double -8.100000e+00, double* %d_addr
+ %d = load double* %d_addr
+ %sd = fptosi double %d to i32
+ %matchesd = icmp eq i32 %sd, -8
+ %err_msgd = getelementptr [21 x i8]* @.strFPToSIDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test casting unsigned int to fp
+define void @testUIToFP() {
+entry:
+ ; unsigned int to float
+ %f = uitofp i32 7 to float
+ %matchesf = fcmp oeq float %f, 7.000000e+00
+ %err_msgf = getelementptr [20 x i8]* @.strUIToFPFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; unsigned int to double
+ %d = uitofp i32 7 to double
+ %matchesd = fcmp oeq double %d, 7.000000e+00
+ %err_msgd = getelementptr [21 x i8]* @.strUIToFPDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test casting signed int to fp
+define void @testSIToFP() {
+entry:
+ ; signed int to float
+ %f = sitofp i32 -7 to float
+ %matchesf = fcmp oeq float %f, -7.000000e+00
+ %err_msgf = getelementptr [20 x i8]* @.strSIToFPFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; signed int to double
+ %d = sitofp i32 -7 to double
+ %matchesd = fcmp oeq double %d, -7.000000e+00
+ %err_msgd = getelementptr [21 x i8]* @.strSIToFPDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; testing fp division
+define void @testFDiv() {
+entry:
+ %fN_addr = alloca float, align 4
+ %fD_addr = alloca float, align 4
+ %dN_addr = alloca double, align 8
+ %dD_addr = alloca double, align 8
+
+ ; float division
+ store float 2.200000e+01, float* %fN_addr
+ store float 4.000000e+00, float* %fD_addr
+ %fN = load float* %fN_addr
+ %fD = load float* %fD_addr
+ %f = fdiv float %fN, %fD
+ %matchesf = fcmp oeq float %f, 5.500000e+00
+ %err_msgf = getelementptr [18 x i8]* @.strDivFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; double division
+ store double 2.200000e+01, double* %dN_addr
+ store double -4.000000e+00, double* %dD_addr
+ %dN = load double* %dN_addr
+ %dD = load double* %dD_addr
+ %d = fdiv double %dN, %dD
+ %matchesd = fcmp oeq double %d, -5.500000e+00
+ %err_msgd = getelementptr [19 x i8]* @.strDivDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; testing fp modulo
+define void @testFRem() {
+entry:
+ %fN_addr = alloca float, align 4
+ %fD_addr = alloca float, align 4
+ %dN_addr = alloca double, align 8
+ %dD_addr = alloca double, align 8
+
+ ; float modoulo
+ store float 2.200000e+01, float* %fN_addr
+ store float 4.000000e+00, float* %fD_addr
+ %fN = load float* %fN_addr
+ %fD = load float* %fD_addr
+ %f = frem float %fN, %fD
+ %matchesf = fcmp oeq float %f, 2.000000e+00
+ %err_msgf = getelementptr [18 x i8]* @.strRemFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; double modulo
+ store double -2.200000e+01, double* %dN_addr
+ store double 4.000000e+00, double* %dD_addr
+ %dN = load double* %dN_addr
+ %dD = load double* %dD_addr
+ %d = frem double %dN, %dD
+ %matchesd = fcmp oeq double %d, -2.000000e+00
+ %err_msgd = getelementptr [19 x i8]* @.strRemDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test addition (fp and int since add is polymorphic)
+define void @testAdd() {
+entry:
+ %f1_addr = alloca float, align 4
+ %f2_addr = alloca float, align 4
+ %d1_addr = alloca double, align 8
+ %d2_addr = alloca double, align 8
+
+ ; test integer addition (3 + 4)
+ %sumi = add i32 3, 4
+ %matchesi = icmp eq i32 %sumi, 7
+ %err_msgi = getelementptr [16 x i8]* @.strAddInt, i32 0, i32 0
+ call void @failCheck( i1 %matchesi, i8* %err_msgi )
+
+ ; test float addition (3.5 + 4.2)
+ store float 3.500000e+00, float* %f1_addr
+ store float 0x4010CCCCC0000000, float* %f2_addr
+ %f1 = load float* %f1_addr
+ %f2 = load float* %f2_addr
+ %sumf = add float %f1, %f2
+ %matchesf = fcmp oeq float %sumf, 0x401ECCCCC0000000
+ %err_msgf = getelementptr [18 x i8]* @.strAddFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; test double addition (3.5 + -4.2)
+ store double 3.500000e+00, double* %d1_addr
+ store double -4.200000e+00, double* %d2_addr
+ %d1 = load double* %d1_addr
+ %d2 = load double* %d2_addr
+ %sumd = add double %d1, %d2
+ %matchesd = fcmp oeq double %sumd, 0xBFE6666666666668
+ %err_msgd = getelementptr [19 x i8]* @.strAddDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test subtraction (fp and int since sub is polymorphic)
+define void @testSub() {
+entry:
+ %f1_addr = alloca float, align 4
+ %f2_addr = alloca float, align 4
+ %d1_addr = alloca double, align 8
+ %d2_addr = alloca double, align 8
+
+ ; test integer subtraction (3 - 4)
+ %subi = sub i32 3, 4
+ %matchesi = icmp eq i32 %subi, -1
+ %err_msgi = getelementptr [16 x i8]* @.strSubInt, i32 0, i32 0
+ call void @failCheck( i1 %matchesi, i8* %err_msgi )
+
+ ; test float subtraction (3.5 - 4.2)
+ store float 3.500000e+00, float* %f1_addr
+ store float 0x4010CCCCC0000000, float* %f2_addr
+ %f1 = load float* %f1_addr
+ %f2 = load float* %f2_addr
+ %subf = sub float %f1, %f2
+ %matchesf = fcmp oeq float %subf, 0xBFE6666600000000
+ %err_msgf = getelementptr [18 x i8]* @.strSubFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; test double subtraction (3.5 - -4.2)
+ store double 3.500000e+00, double* %d1_addr
+ store double -4.200000e+00, double* %d2_addr
+ %d1 = load double* %d1_addr
+ %d2 = load double* %d2_addr
+ %subd = sub double %d1, %d2
+ %matchesd = fcmp oeq double %subd, 7.700000e+00
+ %err_msgd = getelementptr [19 x i8]* @.strSubDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test multiplication (fp and int since mul is polymorphic)
+define void @testMul() {
+entry:
+ %f1_addr = alloca float, align 4
+ %f2_addr = alloca float, align 4
+ %d1_addr = alloca double, align 8
+ %d2_addr = alloca double, align 8
+
+ ; test integer multiplication (3 * 4)
+ %muli = mul i32 3, 4
+ %matchesi = icmp eq i32 %muli, 12
+ %err_msgi = getelementptr [16 x i8]* @.strMulInt, i32 0, i32 0
+ call void @failCheck( i1 %matchesi, i8* %err_msgi )
+
+ ; test float multiplication (3.5 * 4.2)
+ store float 3.500000e+00, float* %f1_addr
+ store float 0x4010CCCCC0000000, float* %f2_addr
+ %f1 = load float* %f1_addr
+ %f2 = load float* %f2_addr
+ %mulf = mul float %f1, %f2
+ %matchesf = fcmp oeq float %mulf, 0x402D666640000000
+ %err_msgf = getelementptr [18 x i8]* @.strMulFlt, i32 0, i32 0
+ call void @failCheck( i1 %matchesf, i8* %err_msgf )
+
+ ; test double multiplication (3.5 * -4.2)
+ store double 3.500000e+00, double* %d1_addr
+ store double -4.200000e+00, double* %d2_addr
+ %d1 = load double* %d1_addr
+ %d2 = load double* %d2_addr
+ %muld = mul double %d1, %d2
+ %matchesd = fcmp oeq double %muld, 0xC02D666666666667
+ %err_msgd = getelementptr [19 x i8]* @.strMulDbl, i32 0, i32 0
+ call void @failCheck( i1 %matchesd, i8* %err_msgd )
+
+ ret void
+}
+
+; test float comparisons (ordered)
+define void @testFCmpFOrdered(float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) {
+entry:
+ ; test fcmp::true -- should always return true
+ %cmp_t = fcmp true float %f1, %f2
+ %cmp_t_ok = icmp eq i1 %cmp_t, 1
+ %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em )
+
+ ; test fcmp::false -- should always return false
+ %cmp_f = fcmp false float %f1, %f2
+ %cmp_f_ok = icmp eq i1 %cmp_f, 0
+ %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em )
+
+ ; test fcmp::ord -- should return true if neither operand is NaN
+ %cmp_o = fcmp ord float %f1, %f2
+ %cmp_o_ok = icmp eq i1 %cmp_o, %ord
+ %cmp_o_em = getelementptr [18 x i8]* @.strCmpOrdFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+ ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal
+ %cmp_eq = fcmp oeq float %f1, %f2
+ %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+ %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+ ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal
+ %cmp_ge = fcmp oge float %f1, %f2
+ %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+ %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+ ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater
+ %cmp_gt = fcmp ogt float %f1, %f2
+ %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+ %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+ ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal
+ %cmp_le = fcmp ole float %f1, %f2
+ %cmp_le_ok = icmp eq i1 %cmp_le, %le
+ %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+ ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less
+ %cmp_lt = fcmp olt float %f1, %f2
+ %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+ %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+ ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal
+ %cmp_ne = fcmp one float %f1, %f2
+ %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+ %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+ ret void
+}
+
+; test double comparisons (ordered)
+define void @testFCmpDOrdered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) {
+entry:
+ ; test fcmp::true -- should always return true
+ %cmp_t = fcmp true double %d1, %d2
+ %cmp_t_ok = icmp eq i1 %cmp_t, 1
+ %cmp_t_em = getelementptr [19 x i8]* @.strCmpTrDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_t_ok, i8* %cmp_t_em )
+
+ ; test fcmp::false -- should always return false
+ %cmp_f = fcmp false double %d1, %d2
+ %cmp_f_ok = icmp eq i1 %cmp_f, 0
+ %cmp_f_em = getelementptr [20 x i8]* @.strCmpFaDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_f_ok, i8* %cmp_f_em )
+
+ ; test fcmp::ord -- should return true if neither operand is NaN
+ %cmp_o = fcmp ord double %d1, %d2
+ %cmp_o_ok = icmp eq i1 %cmp_o, %ord
+ %cmp_o_em = getelementptr [19 x i8]* @.strCmpOrdDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+ ; test fcmp::oeq -- should return true if neither operand is a NaN and they are equal
+ %cmp_eq = fcmp oeq double %d1, %d2
+ %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+ %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+ ; test fcmp::oge -- should return true if neither operand is a NaN and the first is greater or equal
+ %cmp_ge = fcmp oge double %d1, %d2
+ %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+ %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+ ; test fcmp::ogt -- should return true if neither operand is a NaN and the first is greater
+ %cmp_gt = fcmp ogt double %d1, %d2
+ %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+ %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+ ; test fcmp::ole -- should return true if neither operand is a NaN and the first is less or equal
+ %cmp_le = fcmp ole double %d1, %d2
+ %cmp_le_ok = icmp eq i1 %cmp_le, %le
+ %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+ ; test fcmp::olt -- should return true if neither operand is a NaN and the first is less
+ %cmp_lt = fcmp olt double %d1, %d2
+ %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+ %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+ ; test fcmp::one -- should return true if neither operand is a NaN and they are not equal
+ %cmp_ne = fcmp one double %d1, %d2
+ %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+ %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+ ret void
+}
+
+; test floating point comparisons (ordered)
+define void @testFCmpBothOrdered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord) {
+entry:
+ call void @testFCmpDOrdered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord )
+
+ %f1 = fptrunc double %d1 to float
+ %f2 = fptrunc double %d2 to float
+ call void @testFCmpFOrdered( float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord )
+
+ ret void
+}
+
+; test float comparisons (unordered)
+define void @testFCmpFUnordered(float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) {
+entry:
+ ; test fcmp::uno -- should return true if either operand is NaN
+ %cmp_o = fcmp uno float %f1, %f2
+ %cmp_o_ok = icmp eq i1 %cmp_o, %uno
+ %cmp_o_em = getelementptr [20 x i8]* @.strCmpUnoFlt, i32 0, i32 0
+ call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+ ; test fcmp::oeq -- should return true if either operand is a NaN and they are equal
+ %cmp_eq = fcmp ueq float %f1, %f2
+ %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+ %cmp_eq_em = getelementptr [17 x i8]* @.strCmpEqFltU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+ ; test fcmp::oge -- should return true if either operand is a NaN and the first is greater or equal
+ %cmp_ge = fcmp uge float %f1, %f2
+ %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+ %cmp_ge_em = getelementptr [17 x i8]* @.strCmpGeFltU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+ ; test fcmp::ogt -- should return true if either operand is a NaN and the first is greater
+ %cmp_gt = fcmp ugt float %f1, %f2
+ %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+ %cmp_gt_em = getelementptr [17 x i8]* @.strCmpGtFltU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+ ; test fcmp::ole -- should return true if either operand is a NaN and the first is less or equal
+ %cmp_le = fcmp ule float %f1, %f2
+ %cmp_le_ok = icmp eq i1 %cmp_le, %le
+ %cmp_le_em = getelementptr [17 x i8]* @.strCmpLeFltU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+ ; test fcmp::olt -- should return true if either operand is a NaN and the first is less
+ %cmp_lt = fcmp ult float %f1, %f2
+ %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+ %cmp_lt_em = getelementptr [17 x i8]* @.strCmpLtFltU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+ ; test fcmp::one -- should return true if either operand is a NaN and they are not equal
+ %cmp_ne = fcmp une float %f1, %f2
+ %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+ %cmp_ne_em = getelementptr [17 x i8]* @.strCmpNeFltU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+ ret void
+}
+
+; test double comparisons (unordered)
+define void @testFCmpDUnordered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) {
+entry:
+ ; test fcmp::uno -- should return true if either operand is NaN
+ %cmp_o = fcmp uno double %d1, %d2
+ %cmp_o_ok = icmp eq i1 %cmp_o, %uno
+ %cmp_o_em = getelementptr [21 x i8]* @.strCmpUnoDbl, i32 0, i32 0
+ call void @failCheck( i1 %cmp_o_ok, i8* %cmp_o_em )
+
+ ; test fcmp::ueq -- should return true if either operand is a NaN and they are equal
+ %cmp_eq = fcmp ueq double %d1, %d2
+ %cmp_eq_ok = icmp eq i1 %cmp_eq, %eq
+ %cmp_eq_em = getelementptr [18 x i8]* @.strCmpEqDblU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_eq_ok, i8* %cmp_eq_em )
+
+ ; test fcmp::uge -- should return true if either operand is a NaN and the first is greater or equal
+ %cmp_ge = fcmp uge double %d1, %d2
+ %cmp_ge_ok = icmp eq i1 %cmp_ge, %ge
+ %cmp_ge_em = getelementptr [18 x i8]* @.strCmpGeDblU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ge_ok, i8* %cmp_ge_em )
+
+ ; test fcmp::ugt -- should return true if either operand is a NaN and the first is greater
+ %cmp_gt = fcmp ugt double %d1, %d2
+ %cmp_gt_ok = icmp eq i1 %cmp_gt, %gt
+ %cmp_gt_em = getelementptr [18 x i8]* @.strCmpGtDblU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_gt_ok, i8* %cmp_gt_em )
+
+ ; test fcmp::ule -- should return true if either operand is a NaN and the first is less or equal
+ %cmp_le = fcmp ule double %d1, %d2
+ %cmp_le_ok = icmp eq i1 %cmp_le, %le
+ %cmp_le_em = getelementptr [18 x i8]* @.strCmpLeDblU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_le_ok, i8* %cmp_le_em )
+
+ ; test fcmp::ult -- should return true if either operand is a NaN and the first is less
+ %cmp_lt = fcmp ult double %d1, %d2
+ %cmp_lt_ok = icmp eq i1 %cmp_lt, %lt
+ %cmp_lt_em = getelementptr [18 x i8]* @.strCmpLtDblU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_lt_ok, i8* %cmp_lt_em )
+
+ ; test fcmp::une -- should return true if either operand is a NaN and they are not equal
+ %cmp_ne = fcmp une double %d1, %d2
+ %cmp_ne_ok = icmp eq i1 %cmp_ne, %ne
+ %cmp_ne_em = getelementptr [18 x i8]* @.strCmpNeDblU, i32 0, i32 0
+ call void @failCheck( i1 %cmp_ne_ok, i8* %cmp_ne_em )
+
+ ret void
+}
+
+; test floating point comparisons (unordered)
+define void @testFCmpBothUnordered(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno) {
+entry:
+ call void @testFCmpDUnordered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno )
+
+ %f1 = fptrunc double %d1 to float
+ %f2 = fptrunc double %d2 to float
+ call void @testFCmpFUnordered( float %f1, float %f2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno )
+
+ ret void
+}
+
+; test floating point comparisons (ordered and unordered)
+define void @testFCmpBoth(double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord, i1 %uno) {
+entry:
+ call void @testFCmpBothOrdered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %ord )
+ call void @testFCmpBothUnordered( double %d1, double %d2, i1 %eq, i1 %ge, i1 %gt, i1 %le, i1 %lt, i1 %ne, i1 %uno )
+
+ ret void
+}
+
+; test floating point comparisons (ordered and unordered) with a variety of real numbers and NaNs as operands
+define void @testFCmp() {
+entry:
+ %x = alloca i64, align 8
+ %nan = alloca double, align 8
+
+ ; test FCmp on some real number inputs
+ call void @testFCmpBoth( double 0.000000e+00, double 0.000000e+00, i1 1, i1 1, i1 0, i1 1, i1 0, i1 0, i1 1, i1 0 )
+ call void @testFCmpBoth( double 0.000000e+00, double 1.000000e+00, i1 0, i1 0, i1 0, i1 1, i1 1, i1 1, i1 1, i1 0 )
+ call void @testFCmpBoth( double 1.000000e+00, double 0.000000e+00, i1 0, i1 1, i1 1, i1 0, i1 0, i1 1, i1 1, i1 0 )
+
+ ; build NaN
+ store i64 -1, i64* %x
+ %nan_as_i8 = bitcast double* %nan to i8*
+ %x_as_i8 = bitcast i64* %x to i8*
+ call void @llvm.memcpy.i32( i8* %nan_as_i8, i8* %x_as_i8, i32 8, i32 8 )
+
+ ; load two copies of our NaN
+ %nan1 = load double* %nan
+ %nan2 = load double* %nan
+
+ ; Warning: NaN comparisons with normal operators is BROKEN in LLVM JIT v2.0. Fixed in v2.1.
+ ; NaNs do different things depending on ordered vs unordered
+; call void @testFCmpBothOrdered( double %nan1, double 0.000000e+00, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 )
+; call void @testFCmpBothOrdered( double %nan1, double %nan2, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0, i1 0 )
+; call void @testFCmpBothUnordered( double %nan1, double 0.000000e+00, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1 )
+; call void @testFCmpBothUnordered( double %nan1, double %nan2, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1, i1 1 )
+
+ ret void
+}
+
+; tes all floating point instructions
+define i32 @main() {
+entry:
+ call void @testFPTrunc( )
+ call void @testFPExt( )
+ call void @testFPToUI( )
+ call void @testFPToSI( )
+ call void @testUIToFP( )
+ call void @testSIToFP( )
+
+ call void @testFDiv( )
+ call void @testFRem( )
+ call void @testAdd( )
+ call void @testSub( )
+ call void @testMul( )
+
+ call void @testFCmp( )
+
+ ; everything worked -- print a message saying so
+ %works_msg = getelementptr [20 x i8]* @.strWorks, i32 0, i32 0
+ %err_stream = load %struct.stdout** @stdout
+ %ret = call i32 (%struct.stdout*, i8*, ...)* @fprintf( %struct.stdout* %err_stream, i8* %works_msg )
+
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/GlobalInitializers.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/GlobalInitializers.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/GlobalInitializers.ll (added)
+++ klee/trunk/test/Concrete/GlobalInitializers.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,47 @@
+; (cd .. && make) && ../llvm/Release/bin/llvm-as test.ll -o=- | ../Debug/bin/klee
+
+declare void @print_i32(i32)
+
+%simple = type { i8, i16, i32, i64 }
+ at gInt = global i32 2
+ at gInts = global [2 x i32] [ i32 3, i32 5 ]
+ at gStruct = global %simple { i8 7, i16 11, i32 13, i64 17 }
+ at gZero = global %simple zeroinitializer
+
+define i32 @main() {
+entry:
+ %addr0 = getelementptr i32* @gInt, i32 0
+ %addr1 = getelementptr [2 x i32]* @gInts, i32 0, i32 0
+ %addr2 = getelementptr [2 x i32]* @gInts, i32 0, i32 1
+ %addr3 = getelementptr %simple* @gStruct, i32 0, i32 0
+ %addr4 = getelementptr %simple* @gStruct, i32 0, i32 1
+ %addr5 = getelementptr %simple* @gStruct, i32 0, i32 2
+ %addr6 = getelementptr %simple* @gStruct, i32 0, i32 3
+ %addr7 = getelementptr %simple* @gZero, i32 0, i32 2
+ %contents0 = load i32* %addr0
+ %contents1 = load i32* %addr1
+ %contents2 = load i32* %addr2
+ %contents3tmp = load i8* %addr3
+ %contents3 = zext i8 %contents3tmp to i32
+ %contents4tmp = load i16* %addr4
+ %contents4 = zext i16 %contents4tmp to i32
+ %contents5 = load i32* %addr5
+ %contents6tmp = load i64* %addr6
+ %contents6 = trunc i64 %contents6tmp to i32
+ %contents7 = load i32* %addr7
+ %tmp0 = mul i32 %contents0, %contents1
+ %tmp1 = mul i32 %tmp0, %contents2
+ %tmp2 = mul i32 %tmp1, %contents3
+ %tmp3 = mul i32 %tmp2, %contents4
+ %tmp4 = mul i32 %tmp3, %contents5
+ %tmp5 = mul i32 %tmp4, %contents6
+ %tmp6 = add i32 %tmp5, %contents7
+ %p = icmp eq i32 %tmp5, 510510
+ br i1 %p, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Propchange: klee/trunk/test/Concrete/GlobalInitializers.ll
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/test/Concrete/GlobalVariable.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/GlobalVariable.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/GlobalVariable.ll (added)
+++ klee/trunk/test/Concrete/GlobalVariable.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,9 @@
+declare void @print_i32(i32)
+
+ at anInt = global i32 1
+ at aRef = global i32* @anInt
+
+define i32 @main() {
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/ICmp.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/ICmp.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/ICmp.ll (added)
+++ klee/trunk/test/Concrete/ICmp.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,245 @@
+declare void @print_i32(i32)
+
+define i1 @checkSlt() {
+ %c0 = icmp slt i8 -1, 1 ; 1
+ %c1 = icmp slt i8 0, 1 ; 1
+ %c2 = icmp slt i8 1, 1 ; 0
+ %c3 = icmp slt i8 1, -1 ; 0
+ %c4 = icmp slt i8 1, 0 ; 0
+ %c5 = icmp slt i8 1, 1 ; 0
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 3 ; 0bin000011
+ ret i1 %test
+}
+
+define i1 @checkSle() {
+ %c0 = icmp sle i8 -1, 1 ; 1
+ %c1 = icmp sle i8 0, 1 ; 1
+ %c2 = icmp sle i8 1, 1 ; 1
+ %c3 = icmp sle i8 1, -1 ; 0
+ %c4 = icmp sle i8 1, 0 ; 0
+ %c5 = icmp sle i8 1, 1 ; 1
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 39 ; 0bin100111
+ ret i1 %test
+}
+
+define i1 @checkSgt() {
+ %c0 = icmp sgt i8 -1, 1 ; 0
+ %c1 = icmp sgt i8 0, 1 ; 0
+ %c2 = icmp sgt i8 1, 1 ; 0
+ %c3 = icmp sgt i8 1, -1 ; 1
+ %c4 = icmp sgt i8 1, 0 ; 1
+ %c5 = icmp sgt i8 1, 1 ; 0
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 24 ; 0bin011000
+ ret i1 %test
+}
+
+define i1 @checkSge() {
+ %c0 = icmp sge i8 -1, 1 ; 0
+ %c1 = icmp sge i8 0, 1 ; 0
+ %c2 = icmp sge i8 1, 1 ; 1
+ %c3 = icmp sge i8 1, -1 ; 1
+ %c4 = icmp sge i8 1, 0 ; 1
+ %c5 = icmp sge i8 1, 1 ; 1
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 60 ; 0bin111100
+ ret i1 %test
+}
+
+define i1 @checkUlt() {
+ %c0 = icmp ult i8 -1, 1 ; 0
+ %c1 = icmp ult i8 0, 1 ; 1
+ %c2 = icmp ult i8 1, 1 ; 0
+ %c3 = icmp ult i8 1, -1 ; 1
+ %c4 = icmp ult i8 1, 0 ; 0
+ %c5 = icmp ult i8 1, 1 ; 0
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 10 ; 0bin001010
+ ret i1 %test
+}
+
+define i1 @checkUle() {
+ %c0 = icmp ule i8 -1, 1 ; 0
+ %c1 = icmp ule i8 0, 1 ; 1
+ %c2 = icmp ule i8 1, 1 ; 1
+ %c3 = icmp ule i8 1, -1 ; 1
+ %c4 = icmp ule i8 1, 0 ; 0
+ %c5 = icmp ule i8 1, 1 ; 1
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 46 ; 0bin101110
+ ret i1 %test
+}
+
+define i1 @checkUgt() {
+ %c0 = icmp ugt i8 -1, 1 ; 1
+ %c1 = icmp ugt i8 0, 1 ; 0
+ %c2 = icmp ugt i8 1, 1 ; 0
+ %c3 = icmp ugt i8 1, -1 ; 0
+ %c4 = icmp ugt i8 1, 0 ; 1
+ %c5 = icmp ugt i8 1, 1 ; 0
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 17 ; 0bin010001
+ ret i1 %test
+}
+
+define i1 @checkUge() {
+ %c0 = icmp uge i8 -1, 1 ; 1
+ %c1 = icmp uge i8 0, 1 ; 0
+ %c2 = icmp uge i8 1, 1 ; 1
+ %c3 = icmp uge i8 1, -1 ; 0
+ %c4 = icmp uge i8 1, 0 ; 1
+ %c5 = icmp uge i8 1, 1 ; 1
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %a3 = select i1 %c3, i8 8, i8 0
+ %a4 = select i1 %c4, i8 16, i8 0
+ %a5 = select i1 %c5, i8 32, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum1 = add i8 %sum0, %a2
+ %sum2 = add i8 %sum1, %a3
+ %sum3 = add i8 %sum2, %a4
+ %sum = add i8 %sum3, %a5
+ %test = icmp eq i8 %sum, 53 ; 0bin110101
+ ret i1 %test
+}
+
+define i1 @checkEq() {
+ %c0 = icmp eq i8 -1, 1 ; 0
+ %c1 = icmp eq i8 1, 1 ; 1
+ %c2 = icmp eq i8 1, -1 ; 0
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum = add i8 %sum0, %a2
+ %test = icmp eq i8 %sum, 2
+ ret i1 %test
+}
+
+define i1 @checkNe() {
+ %c0 = icmp ne i8 -1, 1 ; 1
+ %c1 = icmp ne i8 1, 1 ; 0
+ %c2 = icmp ne i8 1, -1 ; 1
+ %a0 = select i1 %c0, i8 1, i8 0
+ %a1 = select i1 %c1, i8 2, i8 0
+ %a2 = select i1 %c2, i8 4, i8 0
+ %sum0 = add i8 %a0, %a1
+ %sum = add i8 %sum0, %a2
+ %test = icmp eq i8 %sum, 5
+ ret i1 %test
+}
+
+define i32 @main() {
+ %c0 = call i1 @checkSlt ()
+ %c1 = call i1 @checkSle ()
+ %c2 = call i1 @checkSgt ()
+ %c3 = call i1 @checkSge ()
+ %c4 = call i1 @checkUlt ()
+ %c5 = call i1 @checkUle ()
+ %c6 = call i1 @checkUgt ()
+ %c7 = call i1 @checkUge ()
+ %c8 = call i1 @checkEq ()
+ %c9 = call i1 @checkNe ()
+ %a0 = select i1 %c0, i16 1, i16 0
+ %a1 = select i1 %c1, i16 2, i16 0
+ %a2 = select i1 %c2, i16 4, i16 0
+ %a3 = select i1 %c3, i16 8, i16 0
+ %a4 = select i1 %c4, i16 16, i16 0
+ %a5 = select i1 %c5, i16 32, i16 0
+ %a6 = select i1 %c6, i16 64, i16 0
+ %a7 = select i1 %c7, i16 128, i16 0
+ %a8 = select i1 %c8, i16 256, i16 0
+ %a9 = select i1 %c9, i16 512, i16 0
+ %sum0 = add i16 %a0, %a1
+ %sum1 = add i16 %sum0, %a2
+ %sum2 = add i16 %sum1, %a3
+ %sum3 = add i16 %sum2, %a4
+ %sum4 = add i16 %sum3, %a5
+ %sum5 = add i16 %sum4, %a6
+ %sum6 = add i16 %sum5, %a7
+ %sum7 = add i16 %sum6, %a8
+ %sum8 = add i16 %sum7, %a9
+ %t = shl i16 63, 10
+ %sum = add i16 %sum8, %t
+ %test = icmp eq i16 %sum, -1
+ br i1 %test, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/InvokeAndReturn.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/InvokeAndReturn.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/InvokeAndReturn.ll (added)
+++ klee/trunk/test/Concrete/InvokeAndReturn.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+declare void @print_i32(i32)
+
+define i8 @sum(i8 %a, i8 %b) {
+ %c = add i8 %a, %b
+ ret i8 %c
+}
+
+define i32 @main() {
+ invoke i8 @sum(i8 1, i8 2)
+ to label %continue
+ unwind label %error
+continue:
+ call void @print_i32(i32 1)
+ ret i32 0
+error:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/InvokeAndUnwindOnce.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/InvokeAndUnwindOnce.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/InvokeAndUnwindOnce.ll (added)
+++ klee/trunk/test/Concrete/InvokeAndUnwindOnce.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+declare void @print_i32(i32)
+
+define i8 @sum(i8 %a, i8 %b) {
+ %c = add i8 %a, %b
+ unwind
+}
+
+define i32 @main() {
+ invoke i8 @sum(i8 1, i8 2)
+ to label %continue
+ unwind label %error
+continue:
+ call void @print_i32(i32 1)
+ ret i32 0
+error:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/InvokeAndUnwindTwice.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/InvokeAndUnwindTwice.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/InvokeAndUnwindTwice.ll (added)
+++ klee/trunk/test/Concrete/InvokeAndUnwindTwice.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+declare void @print_i32(i32)
+
+define i8 @myadd(i8 %a, i8 %b) {
+ unwind
+}
+
+define i8 @sum(i8 %a, i8 %b) {
+ %c = call i8 @myadd(i8 %a, i8 %b)
+ ret i8 %c
+}
+
+define i32 @main() {
+ invoke i8 @sum(i8 1, i8 2)
+ to label %continue
+ unwind label %error
+continue:
+ call void @print_i32(i32 1)
+ ret i32 0
+error:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/Makefile (added)
+++ klee/trunk/test/Concrete/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,55 @@
+LEVEL = ../..
+
+# hard-coding bad. will get fixed.
+LCCFLAGS += -O0 -Wall
+LCXXFLAGS += -O0 -Wall
+LLCFLAGS =
+
+test:
+ ./ConcreteTest.py
+
+clean::
+ -rm -rf Output klee-last klee-out* test.log
+ -rm -rf *.bc
+
+# We do not want to make .d files for tests!
+DISABLE_AUTO_DEPENDENCIES=1
+
+include ${LEVEL}/Makefile.common
+
+# Compile from X.c to Output/X.ll
+Output/%.ll: %.c $(LCC1) Output/.dir $(INCLUDES)
+ $(LLVMGCCWITHPATH) --emit-llvm $(CPPFLAGS) $(LCCFLAGS) -S $< -o $@
+
+# Compile from X.cpp to Output/X.ll
+Output/%.ll: %.cpp $(LCC1XX) Output/.dir $(INCLUDES)
+ $(LLVMGXXWITHPATH) --emit-llvm $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@
+
+# Compile from X.cc to Output/X.ll
+Output/%.ll: %.cc $(LCC1XX) Output/.dir $(INCLUDES)
+ $(LLVMGXXWITHPATH) --emit-llvm $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@
+
+# LLVM Assemble from Output/X.ll to Output/X.bc. Output/X.ll must have come
+# from GCC output, so use GCCAS.
+#
+Output/%.bc: Output/%.ll $(LLVMAS)
+ $(LLVMAS) -f $< -o $@
+
+# LLVM Assemble from X.ll to Output/X.bc. Because we are coming directly from
+# LLVM source, use the non-transforming assembler.
+#
+Output/%.bc: %.ll $(LLVMAS) Output/.dir
+ $(LLVMAS) -f $< -o $@
+
+Output/linked_%.bc: Output/%.bc Output/_testingUtils.bc
+ $(LLVMLD) -disable-opt -link-as-library Output/_testingUtils.bc $< -o $@
+
+.PRECIOUS: Output/.dir
+
+## Cancel built-in implicit rules that override above rules
+%: %.s
+
+%: %.c
+
+%.o: %.c
+
Added: klee/trunk/test/Concrete/OneCall.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/OneCall.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/OneCall.ll (added)
+++ klee/trunk/test/Concrete/OneCall.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,12 @@
+declare void @print_i32(i32)
+
+define i32 @sum(i32 %a, i32 %b) {
+ %c = sub i32 %a, %b
+ ret i32 %c
+}
+
+define i32 @main() {
+ %a = call i32 @sum(i32 54, i32 2)
+ call void @print_i32(i32 %a)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/OverlappingPhiNodes.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/OverlappingPhiNodes.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/OverlappingPhiNodes.ll (added)
+++ klee/trunk/test/Concrete/OverlappingPhiNodes.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+ br label %test
+test:
+ %a = phi i32 [10, %entry], [%b, %test]
+ %b = phi i32 [20, %entry], [%a, %test]
+ %c = phi i32 [0, %entry], [1, %test]
+ %d = icmp eq i32 %c, 1
+ br i1 %d, label %exit, label %test
+exit:
+ call void @print_i32(i32 %b)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/Select.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/Select.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/Select.ll (added)
+++ klee/trunk/test/Concrete/Select.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+ %ten = select i1 true, i32 10, i32 0
+ %five = select i1 false, i32 0, i32 5
+ %check = add i32 %ten, %five
+ %test = icmp eq i32 %check, 15
+ br i1 %test, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/Shifts.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/Shifts.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/Shifts.ll (added)
+++ klee/trunk/test/Concrete/Shifts.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,21 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+ %amt = add i8 2, 5
+ %a = shl i8 1, 5
+ %b = lshr i8 %a, 5
+ %c = shl i8 %b, %amt
+ %d = lshr i8 %c, %amt
+ %e = shl i8 %d, 7
+ %f = ashr i8 %e, 7
+ %g = shl i8 %f, %amt
+ %h = ashr i8 %g, %amt
+ %test = icmp eq i8 %h, -1
+ br i1 %test, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/SimpleStoreAndLoad.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/SimpleStoreAndLoad.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/SimpleStoreAndLoad.ll (added)
+++ klee/trunk/test/Concrete/SimpleStoreAndLoad.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+ %a = alloca i32, i32 4
+ %tmp1 = getelementptr i32* %a, i32 0
+ store i32 0, i32* %tmp1
+ %tmp2 = load i32* %tmp1
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %exitTrue, label %exitFalse
+exitTrue:
+ call void @print_i32(i32 1)
+ ret i32 0
+exitFalse:
+ call void @print_i32(i32 0)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/UnconditionalBranch.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/UnconditionalBranch.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/UnconditionalBranch.ll (added)
+++ klee/trunk/test/Concrete/UnconditionalBranch.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+ %a = add i32 0, 1
+ br label %exit
+exit:
+ call void @print_i32(i32 %a)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/UnconditionalBranchWithSimplePhi.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/UnconditionalBranchWithSimplePhi.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/UnconditionalBranchWithSimplePhi.ll (added)
+++ klee/trunk/test/Concrete/UnconditionalBranchWithSimplePhi.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,14 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+ %a = add i32 0, 1
+ br label %exit
+unused:
+ %b = add i32 1, 2
+ br label %exit
+exit:
+ %c = phi i32 [%a, %entry], [%b, %unused]
+ call void @print_i32(i32 %c)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/UnorderedPhiNodes.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/UnorderedPhiNodes.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/UnorderedPhiNodes.ll (added)
+++ klee/trunk/test/Concrete/UnorderedPhiNodes.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+declare void @print_i32(i32)
+
+define i32 @main() {
+entry:
+ br label %test
+test:
+ %a = phi i32 [10, %entry], [%b, %test]
+ %b = phi i32 [%a, %test], [20, %entry]
+ %c = phi i32 [0, %entry], [1, %test]
+ %d = icmp eq i32 %c, 1
+ br i1 %d, label %exit, label %test
+exit:
+ call void @print_i32(i32 %b)
+ ret i32 0
+}
Added: klee/trunk/test/Concrete/_testingUtils.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/_testingUtils.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/_testingUtils.c (added)
+++ klee/trunk/test/Concrete/_testingUtils.c Wed May 20 23:36:41 2009
@@ -0,0 +1,32 @@
+int putchar(int x);
+
+void print_int(unsigned long long val);
+
+#define TYPED_PRINT(_name_type, _arg_type) \
+ void print_ ## _name_type(_arg_type val) { print_int(val); }
+
+TYPED_PRINT(i1, unsigned char)
+TYPED_PRINT(i8, unsigned char)
+TYPED_PRINT(i16, unsigned short)
+TYPED_PRINT(i32, unsigned int)
+TYPED_PRINT(i64, unsigned long long)
+
+void print_int(unsigned long long val) {
+ int cur = 1;
+
+ // effectively do a log (can't call log because it returns floats)
+ // do the nasty divide to prevent overflow
+ while (cur <= val / 10)
+ cur *= 10;
+
+ while (cur) {
+ int digit = val / cur;
+
+ putchar(digit + '0');
+
+ val = val % cur;
+ cur /= 10;
+ }
+
+ putchar('\n');
+}
Added: klee/trunk/test/Concrete/ackermann.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/ackermann.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/ackermann.c (added)
+++ klee/trunk/test/Concrete/ackermann.c Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+// llvm-gcc -O2 --emit-llvm -c ackermann.c && ../../Debug/bin/klee ackermann.o 2 2
+
+#include <stdio.h>
+
+int ackermann(int m, int n) {
+ if (m == 0)
+ return n+1;
+ else
+ return ackermann(m-1, (n==0) ? 1 : ackermann(m, n-1));
+ }
+
+int main() {
+ printf("ackerman(%d, %d) = %d\n", 2, 2, ackermann(2, 2));
+
+ return 0;
+}
Added: klee/trunk/test/Concrete/arith_test.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Concrete/arith_test.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Concrete/arith_test.ll (added)
+++ klee/trunk/test/Concrete/arith_test.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,76 @@
+define void @"test_simple_arith"(i16 %i0, i16 %j0)
+begin
+ %t1 = add i16 %i0, %j0
+ %t2 = sub i16 %i0, %j0
+ %t3 = mul i16 %t1, %t2
+
+ call void @print_i16(i16 %t3)
+
+ ret void
+end
+
+define void @"test_div_and_mod"(i16 %op1, i16 %op2)
+begin
+ %t1 = udiv i16 %op1, %op2
+ %t2 = urem i16 %op1, %op2
+ %t3 = sdiv i16 %op1, %op2
+ %t4 = srem i16 %op1, %op2
+
+ call void @print_i16(i16 %t1)
+ call void @print_i16(i16 %t2)
+ call void @print_i16(i16 %t3)
+ call void @print_i16(i16 %t4)
+
+ ret void
+end
+
+define void @test_cmp(i16 %op1, i16 %op2)
+begin
+ %t1 = icmp ule i16 %op1, %op2
+ %t2 = icmp ult i16 %op1, %op2
+ %t3 = icmp uge i16 %op1, %op2
+ %t4 = icmp ugt i16 %op1, %op2
+ %t6 = icmp slt i16 %op1, %op2
+ %t5 = icmp sle i16 %op1, %op2
+ %t7 = icmp sge i16 %op1, %op2
+ %t8 = icmp sgt i16 %op1, %op2
+ %t9 = icmp eq i16 %op1, %op2
+ %t10 = icmp ne i16 %op1, %op2
+
+ call void @print_i1(i1 %t1)
+ call void @print_i1(i1 %t2)
+ call void @print_i1(i1 %t3)
+ call void @print_i1(i1 %t4)
+ call void @print_i1(i1 %t5)
+ call void @print_i1(i1 %t6)
+ call void @print_i1(i1 %t7)
+ call void @print_i1(i1 %t8)
+ call void @print_i1(i1 %t9)
+ call void @print_i1(i1 %t10)
+
+ ret void
+end
+
+define i32 @main()
+begin
+ call void @test_simple_arith(i16 111, i16 100)
+
+ call void @test_div_and_mod(i16 63331, i16 3123)
+ call void @test_div_and_mod(i16 1000, i16 55444)
+ call void @test_div_and_mod(i16 49012, i16 55444)
+ call void @test_div_and_mod(i16 1000, i16 25)
+
+ call void @test_cmp(i16 63331, i16 3123)
+ call void @test_cmp(i16 1000, i16 55444)
+ call void @test_cmp(i16 49012, i16 55444)
+ call void @test_cmp(i16 1000, i16 25)
+
+ ret i32 0
+end
+
+; defined in print_int.c
+declare void @print_i1(i1)
+declare void @print_i8(i8)
+declare void @print_i16(i16)
+declare void @print_i32(i32)
+declare void @print_i64(i64)
Added: klee/trunk/test/Coverage/ReadArgs.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Coverage/ReadArgs.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Coverage/ReadArgs.c (added)
+++ klee/trunk/test/Coverage/ReadArgs.c Wed May 20 23:36:41 2009
@@ -0,0 +1,9 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: rm -rf xxx
+// RUN: echo " --output-dir=xxx " > %t1.args
+// RUN: %klee --read-args %t1.args %t1.bc
+// RUN: test -d xxx
+
+int main() {
+ return 0;
+}
Added: klee/trunk/test/Coverage/ReplayOutDir.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Coverage/ReplayOutDir.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Coverage/ReplayOutDir.c (added)
+++ klee/trunk/test/Coverage/ReplayOutDir.c Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: rm -rf %t1.out %t1.replay
+// RUN: %klee --output-dir=%t1.out %t1.bc
+// RUN: %klee --output-dir=%t1.replay --replay-out-dir=%t1.out %t1.bc
+
+int main() {
+ int i;
+ klee_make_symbolic(&i, sizeof i);
+ klee_print_range("i", i);
+ return 0;
+}
Added: klee/trunk/test/Coverage/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Coverage/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Coverage/dg.exp (added)
+++ klee/trunk/test/Coverage/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
Added: klee/trunk/test/Dogfood/ImmutableSet.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Dogfood/ImmutableSet.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Dogfood/ImmutableSet.cpp (added)
+++ klee/trunk/test/Dogfood/ImmutableSet.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,134 @@
+// RUN: llvm-g++ -I../../../include -g -DMAX_ELEMENTS=4 -fno-exceptions --emit-llvm -c -o %t1.bc %s
+// RUN: %klee --libc=klee --max-forks=200 --no-output --exit-on-error --optimize --disable-inlining --use-non-uniform-random-search --use-cex-cache %t1.bc
+
+#include "klee/klee.h"
+#include "klee/Internal/ADT/ImmutableSet.h"
+
+using namespace klee;
+
+typedef ImmutableSet<unsigned> T;
+
+bool iff(bool a, bool b) {
+ return !!a == !!b;
+}
+
+template<typename InputIterator, typename T>
+bool contains(InputIterator begin, InputIterator end, T item) {
+ for (; begin!=end; ++begin)
+ if (*begin == item)
+ return true;
+ return false;
+}
+
+bool equal(T &a, T &b) {
+ T::iterator aIt=a.begin(), ae=a.end(), bIt=b.begin(), be=b.end();
+ for (; aIt!=ae && bIt!=be; ++aIt, ++bIt)
+ if (*aIt != *bIt)
+ return false;
+ if (aIt!=ae) return false;
+ if (bIt!=be) return false;
+ return true;
+}
+
+template<typename InputIterator, typename T>
+void remove(InputIterator begin, InputIterator end, T item) {
+ InputIterator out = begin;
+ for (; begin!=end; ++begin) {
+ if (*begin!=item) {
+ if (out!=begin)
+ *out = *begin;
+ ++out;
+ }
+ }
+}
+
+void check_set(T &set, unsigned num, unsigned *values) {
+ assert(set.size() == num);
+
+ // must contain only values
+ unsigned item = klee_range(0, 256, "range");
+ assert(iff(contains(values, values+num, item),
+ set.count(item)));
+
+ // each value must be findable, must be its own lower bound, and
+ // must be one behind its upper bound
+ for (unsigned i=0; i<num; i++) {
+ unsigned item = values[i];
+ assert(set.count(item));
+ T::iterator it = set.find(item);
+ T::iterator lb = set.lower_bound(item);
+ T::iterator ub = set.upper_bound(item);
+ assert(it != set.end()); // must exit
+ assert(*it == item); // must be itself
+ assert(lb == it); // must be own lower bound
+ assert(--ub == it); // must be one behind upper
+ }
+
+ // for items not in the set...
+ unsigned item2 = klee_range(0, 256, "range");
+ if (!set.count(item2)) {
+ assert(set.find(item2) == set.end());
+
+ T::iterator lb = set.lower_bound(item2);
+ for (T::iterator it=set.begin(); it!=lb; ++it)
+ assert(*it < item2);
+ for (T::iterator it=lb, ie=set.end(); it!=ie; ++it)
+ assert(*it >= item2);
+
+ T::iterator ub = set.upper_bound(item2);
+ for (T::iterator it=set.begin(); it!=ub; ++it)
+ assert(*it <= item2);
+ for (T::iterator it=ub, ie=set.end(); it!=ie; ++it)
+ assert(*it > item2);
+ }
+}
+
+#ifndef MAX_ELEMENTS
+#define MAX_ELEMENTS 4
+#endif
+
+void test() {
+ unsigned num=0, values[MAX_ELEMENTS];
+ T set;
+
+ assert(MAX_ELEMENTS >= 0);
+ for (unsigned i=0; i<klee_range(0,MAX_ELEMENTS+1, "range"); i++) {
+ unsigned item = klee_range(0, 256, "range");
+ if (contains(values, values+num, item))
+ klee_silent_exit(0);
+
+ set = set.insert(item);
+ values[num++] = item;
+ }
+
+ check_set(set, num, values);
+
+ unsigned item = klee_range(0, 256, "range");
+ if (contains(values, values+num, item)) { // in tree
+ // insertion is invariant
+ T set2 = set.insert(item);
+ assert(equal(set2, set));
+
+ // check remove
+ T set3 = set.remove(item);
+ assert(!equal(set3, set)); // mostly just for coverage
+ assert(set3.size() + 1 == set.size());
+ assert(!set3.count(item));
+ } else { // not in tree
+ // removal is invariant
+ T set2 = set.remove(item);
+ assert(equal(set2, set));
+
+ // check insert
+ T set3 = set.insert(item);
+ assert(!equal(set3, set)); // mostly just for coverage
+ assert(set3.size() == set.size() + 1);
+ assert(set3.count(item));
+ }
+}
+
+int main(int argc, char **argv) {
+ test();
+ assert(T::getAllocated() == 0);
+ return 0;
+}
Added: klee/trunk/test/Dogfood/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Dogfood/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Dogfood/dg.exp (added)
+++ klee/trunk/test/Dogfood/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
Added: klee/trunk/test/Expr/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Expr/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Expr/dg.exp (added)
+++ klee/trunk/test/Expr/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
Added: klee/trunk/test/Feature/Alias.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/Alias.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/Alias.c (added)
+++ klee/trunk/test/Feature/Alias.c Wed May 20 23:36:41 2009
@@ -0,0 +1,25 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+// Darwin does not have strong aliases.
+// XFAIL: darwin
+
+#include <assert.h>
+
+// alias for global
+int b = 52;
+extern int a __attribute__((alias("b")));
+
+// alias for function
+int __foo() { return 52; }
+extern int foo() __attribute__((alias("__foo")));
+
+int *c = &a;
+
+int main() {
+ assert(a == 52);
+ assert(foo() == 52);
+ assert(*c == 52);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/AliasFunction.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/AliasFunction.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/AliasFunction.c (added)
+++ klee/trunk/test/Feature/AliasFunction.c Wed May 20 23:36:41 2009
@@ -0,0 +1,33 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc > %t1.log
+// RUN: grep -c foo %t1.log | grep 5
+// RUN: grep -c bar %t1.log | grep 3
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void foo() { printf(" foo()\n"); }
+void bar() { printf(" bar()\n"); }
+
+int main() {
+ int x;
+ klee_make_symbolic_name(&x, sizeof(x), "x");
+
+ // no aliases
+ foo();
+
+ if (x > 10)
+ {
+ // foo -> bar
+ klee_alias_function("foo", "bar");
+
+ if (x > 20)
+ foo();
+ }
+
+ foo();
+
+ // undo
+ klee_alias_function("foo", "foo");
+ foo();
+}
Added: klee/trunk/test/Feature/AliasFunctionExit.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/AliasFunctionExit.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/AliasFunctionExit.c (added)
+++ klee/trunk/test/Feature/AliasFunctionExit.c Wed May 20 23:36:41 2009
@@ -0,0 +1,30 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc > %t1.log
+// RUN: grep -c START %t1.log | grep 1
+// RUN: grep -c END %t1.log | grep 2
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void start(int x) {
+ printf("START\n");
+ if (x == 53)
+ exit(1);
+}
+
+void end(int status) {
+ klee_alias_function("exit", "exit");
+ printf("END: status = %d\n", status);
+ exit(status);
+}
+
+
+int main() {
+ int x;
+ klee_make_symbolic_name(&x, sizeof(x), "x");
+
+ klee_alias_function("exit", "end");
+ start(x);
+ end(0);
+}
Added: klee/trunk/test/Feature/AsmAddresses.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/AsmAddresses.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/AsmAddresses.c (added)
+++ klee/trunk/test/Feature/AsmAddresses.c Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+// RUN: %llvmgcc -g -c -o %t.bc %s
+// RUN: %klee --exit-on-error --use-asm-addresses %t.bc
+// RUN: %llvmgcc -DOVERLAP -g -c -o %t.bc %s
+// RUN: not %klee --exit-on-error --use-asm-addresses %t.bc
+
+#include <assert.h>
+
+
+volatile unsigned char x0 __asm ("0x0021");
+volatile unsigned char whee __asm ("0x0WHEE");
+
+#ifdef OVERLAP
+volatile unsigned int y0 __asm ("0x0030");
+volatile unsigned int y1 __asm ("0x0032");
+#endif
+
+int main() {
+ assert(&x0 == (void*) 0x0021);
+ assert(&whee != (void*) 0x0);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/ByteSwap.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/ByteSwap.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/ByteSwap.c (added)
+++ klee/trunk/test/Feature/ByteSwap.c Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --libc=klee --exit-on-error %t1.bc
+
+#include <arpa/inet.h>
+#include <assert.h>
+
+int main() {
+
+ uint32_t n = 0;
+ klee_make_symbolic(&n, sizeof(n));
+
+ uint32_t h = ntohl(n);
+ assert(htonl(h) == n);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/CallToUndefinedExternal.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/CallToUndefinedExternal.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/CallToUndefinedExternal.cpp (added)
+++ klee/trunk/test/Feature/CallToUndefinedExternal.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.external.err
+
+extern "C" void poof(void);
+
+int main() {
+ poof();
+
+ return 0;
+}
Added: klee/trunk/test/Feature/CheckForImpliedValue.c.failing
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/CheckForImpliedValue.c.failing?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/CheckForImpliedValue.c.failing (added)
+++ klee/trunk/test/Feature/CheckForImpliedValue.c.failing Wed May 20 23:36:41 2009
@@ -0,0 +1,23 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: rm -f %t1.log
+// RUN: %klee --log-file %t1.log --debug-check-for-implied-values %t1.bc
+// RUN: grep "= 0 (ok)" %t1.log
+// RUN: grep "= 2 (missed)" %t1.log
+
+#define swap(x) (((x)>>16) | (((x)&0xFFFF)<<16))
+int main() {
+ unsigned x, y;
+
+ klee_make_symbolic(&x, sizeof x);
+ klee_make_symbolic(&y, sizeof y);
+
+ if (!x) { // should give x = 0 hit by ivc
+ printf("ok\n");
+ } else {
+ if (swap(y) == 0x00020000) { // should give y = 2 missed by ivc
+ printf("ok\n");
+ }
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/CheckMemoryAccess.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/CheckMemoryAccess.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/CheckMemoryAccess.c (added)
+++ klee/trunk/test/Feature/CheckMemoryAccess.c Wed May 20 23:36:41 2009
@@ -0,0 +1,26 @@
+// RUN: %llvmgcc -g -c %s -o %t.bc
+// RUN: %klee %t.bc > %t.log
+// RUN: grep -q "good" %t.log
+// RUN: not grep -q "bad" %t.log
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main() {
+ char buf[4];
+
+ klee_check_memory_access(&buf, 1);
+ printf("good\n");
+ if (klee_range(0, 2, "range1")) {
+ klee_check_memory_access(0, 1);
+ printf("null pointer deref: bad\n");
+ }
+
+ if (klee_range(0, 2, "range2")) {
+ klee_check_memory_access(buf, 5);
+ printf("oversize access: bad\n");
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/CopyOnWrite.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/CopyOnWrite.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/CopyOnWrite.c (added)
+++ klee/trunk/test/Feature/CopyOnWrite.c Wed May 20 23:36:41 2009
@@ -0,0 +1,26 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --use-random-search --exit-on-error %t1.bc
+
+#include <assert.h>
+
+#define N 5
+
+unsigned branches = 0;
+
+void explode(int *ap, int i, int *result) {
+ if (i<N) {
+ (*result)++;
+ if (ap[i]) // just cause a fork
+ branches++;
+ return explode(ap, i+1, result);
+ }
+}
+
+int main() {
+ int result = 0;
+ int a[N];
+ klee_make_symbolic(a, sizeof a);
+ explode(a,0,&result);
+ assert(result==N);
+ return 0;
+}
Added: klee/trunk/test/Feature/DanglingConcreteReadExpr.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/DanglingConcreteReadExpr.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/DanglingConcreteReadExpr.c (added)
+++ klee/trunk/test/Feature/DanglingConcreteReadExpr.c Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: grep "total queries = 2" klee-last/info
+
+#include <assert.h>
+
+int main() {
+ unsigned char x, y;
+
+ klee_make_symbolic(&x, sizeof x);
+
+ y = x;
+
+ // should be exactly two queries (prove x is/is not 10)
+ // eventually should be 0 when we have fast solver
+ if (x==10) {
+ assert(y==10);
+ }
+
+ klee_silent_exit(0);
+ return 0;
+}
Added: klee/trunk/test/Feature/DefineFixedObject.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/DefineFixedObject.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/DefineFixedObject.c (added)
+++ klee/trunk/test/Feature/DefineFixedObject.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+// RUN: %llvmgcc -c -o %t1.bc %s
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <stdio.h>
+
+#define ADDRESS ((int*) 0x0080)
+
+int main() {
+ klee_define_fixed_object(ADDRESS, 4);
+
+ int *p = ADDRESS;
+
+ *p = 10;
+ printf("*p: %d\n", *p);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/DoubleFree.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/DoubleFree.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/DoubleFree.c (added)
+++ klee/trunk/test/Feature/DoubleFree.c Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.ptr.err
+
+int main() {
+ int *x = malloc(4);
+ free(x);
+ free(x);
+ return 0;
+}
Added: klee/trunk/test/Feature/DumpStatesOnHalt.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/DumpStatesOnHalt.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/DumpStatesOnHalt.c (added)
+++ klee/trunk/test/Feature/DumpStatesOnHalt.c Wed May 20 23:36:41 2009
@@ -0,0 +1,8 @@
+// RUN: %llvmgcc %s -g -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --stop-after-n-instructions=1 --dump-states-on-halt=true %t1.bc
+// RUN: test -f klee-last/test000001.bout
+
+int main() {
+ int x = 10;
+ return x;
+}
Added: klee/trunk/test/Feature/Envp.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/Envp.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/Envp.c (added)
+++ klee/trunk/test/Feature/Envp.c Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <assert.h>
+
+int main(int argc, char **argv, char **envp) {
+ unsigned i;
+ assert(argv[argc] == 0);
+ printf("argc: %d, argv: %p, envp: %p\n", argc, argv, envp);
+ printf("--environ--\n");
+ int haspwd = 0;
+ for (i=0; envp[i]; i++) {
+ printf("%d: %s\n", i, envp[i]);
+ haspwd |= strncmp(envp[i], "PWD=", 4)==0;
+ }
+ assert(haspwd);
+ return 0;
+}
Added: klee/trunk/test/Feature/ExprLogging.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/ExprLogging.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/ExprLogging.c (added)
+++ klee/trunk/test/Feature/ExprLogging.c Wed May 20 23:36:41 2009
@@ -0,0 +1,43 @@
+// RUN: %llvmgcc %s -emit-llvm -g -O0 -c -o %t1.bc
+// RUN: %klee --use-query-pc-log --write-pcs --write-cvcs %t1.bc 2> %t2.log
+// RUN: %kleaver -print-ast klee-last/test000001.pc
+
+// FIXME: Ideally we would verify a roundtrip that we parsed the pc
+// file and can dump it back out as the same file.
+
+#include <assert.h>
+
+int constantArr[16 ] = {
+ 1 << 0, 1 << 1, 1 << 2, 1 << 3,
+ 1 << 4, 1 << 5, 1 << 6, 1 << 7,
+ 1 << 8, 1 << 9, 1 << 10, 1 << 11,
+ 1 << 12, 1 << 13, 1 << 14, 1 << 15
+};
+
+
+int main() {
+ char buf[4];
+ klee_make_symbolic(buf, sizeof buf);
+
+ buf[1] = 'a';
+
+ constantArr[klee_range(0, 16, "idx.0")] = buf[0];
+
+ // Use this to trigger an interior update list usage.
+ int y = constantArr[klee_range(0, 16, "idx.1")];
+
+ constantArr[klee_range(0, 16, "idx.2")] = buf[3];
+
+ buf[klee_range(0, 4, "idx.3")] = 0;
+ klee_assume(buf[0] == 'h');
+
+ int x = *((int*) buf);
+ klee_assume(x > 2);
+ klee_assume(x == constantArr[12]);
+
+ klee_assume(y != (1 << 5));
+
+ assert(0);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/ExternalWeakLinkage.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/ExternalWeakLinkage.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/ExternalWeakLinkage.c (added)
+++ klee/trunk/test/Feature/ExternalWeakLinkage.c Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <assert.h>
+
+void __attribute__((weak)) IAmSoWeak(int);
+
+int main() {
+ assert(IAmSoWeak==0);
+ return 0;
+}
Added: klee/trunk/test/Feature/FunctionPointer.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/FunctionPointer.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/FunctionPointer.c (added)
+++ klee/trunk/test/Feature/FunctionPointer.c Wed May 20 23:36:41 2009
@@ -0,0 +1,36 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --no-output --exit-on-error %t1.bc
+
+#include <stdio.h>
+
+void foo(const char *msg) { printf("foo: %s\n", msg); }
+void baz(const char *msg) { printf("baz: %s\n", msg); }
+
+void (*xx)(const char *) = foo;
+
+void bar(void (*fp)(const char *)) { fp("called via bar"); }
+
+int main(int argc, char **argv) {
+ void (*fp)(const char *) = foo;
+
+ printf("going to call through fp\n");
+ fp("called via fp");
+
+ printf("calling via pass through\n");
+ bar(foo);
+
+ fp = baz;
+ fp("called via fp");
+
+ xx("called via xx");
+
+#if 0
+ klee_make_symbolic(&fp, sizeof fp);
+ if(fp == baz) {
+ printf("fp = %p, baz = %p\n", fp, baz);
+ fp("calling via symbolic!");
+ }
+#endif
+
+ return 0;
+}
Added: klee/trunk/test/Feature/GetValue.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/GetValue.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/GetValue.c (added)
+++ klee/trunk/test/Feature/GetValue.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+// RUN: %llvmgcc -c -o %t1.bc %s
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <stdio.h>
+#include <assert.h>
+
+int main() {
+ int x = klee_int("x");
+ klee_assume(x > 10);
+ klee_assume(x < 20);
+
+ assert(!klee_is_symbolic(klee_get_value(x)));
+ assert(klee_get_value(x) > 10);
+ assert(klee_get_value(x) < 20);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/ImpliedValue.c.failing
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/ImpliedValue.c.failing?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/ImpliedValue.c.failing (added)
+++ klee/trunk/test/Feature/ImpliedValue.c.failing Wed May 20 23:36:41 2009
@@ -0,0 +1,147 @@
+// RUN: rm -f %t4.out %t4.err %t4.log
+// RUN: %llvmgcc %s -emit-llvm -O2 -c -o %t1.bc
+// RUN: llvm-as -f ../_utils._ll -o %t2.bc
+// RUN: llvm-ld -disable-opt -link-as-library %t1.bc %t2.bc -o %t3.bc
+// RUN: %klee --log-file %t4.log --debug-check-for-implied-values %t3.bc > %t4.out 2> %t4.err
+// RUN: ls klee-last | not grep .err
+// RUN: not grep "(missed)" %t4.log
+
+#include <assert.h>
+
+#include "utils.h"
+
+int main() {
+ unsigned char which;
+ volatile unsigned char a,b,c,d,e,f,g,h;
+
+ klee_make_symbolic(&which, sizeof which);
+ klee_make_symbolic(&a, sizeof a);
+ klee_make_symbolic(&b, sizeof b);
+ klee_make_symbolic(&c, sizeof c);
+ klee_make_symbolic(&d, sizeof d);
+ klee_make_symbolic(&e, sizeof e);
+ klee_make_symbolic(&f, sizeof f);
+ klee_make_symbolic(&g, sizeof g);
+ klee_make_symbolic(&h, sizeof h);
+
+ switch (which) {
+// RUN: grep "simple read(2) = value case" %t4.out
+ case 0:
+ if (a == 2) {
+ assert(!klee_is_symbolic(a));
+ printf("simple read(%d) = value case\n", a);
+ }
+ break;
+
+// RUN: grep "select(0) has distinct constant result case (false)" %t4.out
+ case 1:
+ if (util_make_select(a, 12, 14) == 14) {
+ assert(!klee_is_symbolic(a));
+ printf("select(%d) has distinct constant result case (false)\n", a);
+ }
+ break;
+
+// RUN: grep "select(0) has distinct constant result case (true)" %t4.out
+ case 2:
+ if (util_make_select(!a, 12, 14) == 12) {
+ assert(!klee_is_symbolic(a));
+ printf("select(%d) has distinct constant result case (true)\n", a);
+ }
+ break;
+
+// RUN: grep "concat2(0xBE,0xEF) = value case" %t4.out
+ case 3:
+ if (util_make_concat2(a,b) == 0xBEEF) {
+ assert(!klee_is_symbolic(a));
+ assert(!klee_is_symbolic(b));
+ printf("concat2(0x%X,0x%X) = value case\n",
+ a, b);
+ }
+ break;
+
+// RUN: grep "concat4(0xDE,0xAD,0xBE,0xEF) = value case" %t4.out
+ case 4:
+ if (util_make_concat4(a,b,c,d) == 0xDEADBEEF) {
+ assert(!klee_is_symbolic(a));
+ assert(!klee_is_symbolic(b));
+ assert(!klee_is_symbolic(c));
+ assert(!klee_is_symbolic(d));
+ printf("concat4(0x%X,0x%X,0x%X,0x%X) = value case\n",
+ a, b, c, d);
+ }
+ break;
+
+// RUN: grep "concat8(0xDE,0xAD,0xBE,0xEF,0xAB,0xCD,0xAB,0xCD) = value case" %t4.out
+ case 5:
+ if (util_make_concat8(a,b,c,d,e,f,g,h) == 0xDEADBEEFABCDABCDLL) {
+ assert(!klee_is_symbolic(a));
+ assert(!klee_is_symbolic(b));
+ assert(!klee_is_symbolic(c));
+ assert(!klee_is_symbolic(d));
+ assert(!klee_is_symbolic(e));
+ assert(!klee_is_symbolic(f));
+ assert(!klee_is_symbolic(g));
+ assert(!klee_is_symbolic(h));
+ printf("concat8(0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X) = value case\n",
+ a, b, c, d, e, f, g, h);
+ }
+ break;
+
+// RUN: grep "and(0,0) = true case" %t4.out
+ case 6:
+ if (util_make_and_i1(!a, !b)) {
+ assert(!klee_is_symbolic(a));
+ assert(!klee_is_symbolic(b));
+ printf("and(%d,%d) = true case\n", a, b);
+ }
+ break;
+
+// RUN: grep "or(0,0) = false case" %t4.out
+ case 7:
+ if (!util_make_or_i1(a, b)) {
+ assert(!klee_is_symbolic(a));
+ assert(!klee_is_symbolic(b));
+ printf("or(%d,%d) = false case\n", a, b);
+ }
+ break;
+
+ // we use concat to prevent folding, will need to fix if that gets
+ // partial evaluated
+// RUN: grep "add constant case: 0xDE" %t4.out
+ case 8:
+ if (util_make_concat2(a+0xCD,0xCD) == 0xABCD) {
+ assert(!klee_is_symbolic(a));
+ printf("add constant case: 0x%X\n", a);
+ }
+ break;
+
+// RUN: grep "sub constant case: 0x60" %t4.out
+ case 9:
+ if (util_make_concat2(0x0B-a,0xCD) == 0xABCD) {
+ assert(!klee_is_symbolic(a));
+ printf("sub constant case: 0x%X\n", a);
+ }
+ break;
+
+// RUN: grep "xor constant case: 0xA0" %t4.out
+ case 10:
+ if (util_make_concat2(0x0B ^ a,0xCD) == 0xABCD) {
+ assert(!klee_is_symbolic(a));
+ printf("xor constant case: 0x%X\n", a);
+ }
+ break;
+
+// RUN: grep "sext constant case: 244" %t4.out
+ case 11:
+ if (! util_make_or_i1(((short) (signed char) a) + 12,b)) {
+ assert(!klee_is_symbolic(a));
+ printf("sext constant case: %d\n", a);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/InAndOutOfBounds.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/InAndOutOfBounds.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/InAndOutOfBounds.c (added)
+++ klee/trunk/test/Feature/InAndOutOfBounds.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.ptr.err -o -f klee-last/test000002.ptr.err
+// RUN: test ! -f klee-last/test000001.ptr.err -o ! -f klee-last/test000002.ptr.err
+// RUN: test ! -f klee-last/test000003.bout
+
+unsigned klee_urange(unsigned start, unsigned end) {
+ unsigned x;
+ klee_make_symbolic(&x, sizeof x);
+ if (x-start>=end-start) klee_silent_exit(0);
+ return x;
+}
+
+int main() {
+ int *x = malloc(4);
+ x[klee_urange(0,2)] = 1;
+ free(x);
+ return 0;
+}
Added: klee/trunk/test/Feature/IndirectCallToBuiltin.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/IndirectCallToBuiltin.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/IndirectCallToBuiltin.c (added)
+++ klee/trunk/test/Feature/IndirectCallToBuiltin.c Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int main() {
+ void *(*allocator)(size_t) = malloc;
+ int *mem = allocator(10);
+
+ printf("mem: %p\n", mem);
+ printf("mem[0]: %d\n", mem[0]);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/IndirectCallToExternal.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/IndirectCallToExternal.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/IndirectCallToExternal.c (added)
+++ klee/trunk/test/Feature/IndirectCallToExternal.c Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int main() {
+ int (*scmp)(char*,char*) = strcmp;
+
+ assert(scmp("hello","hi") < 0);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/InvalidBitfieldAccess.c.failing
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/InvalidBitfieldAccess.c.failing?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/InvalidBitfieldAccess.c.failing (added)
+++ klee/trunk/test/Feature/InvalidBitfieldAccess.c.failing Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+// RUN: %llvmgcc -c -o %t1.bc %s
+// RUN: %klee --exit-on-error %t1.bc
+
+// This is a bug in llvm-gcc4.0 but seems to be fixed in llvm-gcc4.2,
+// its included here mostly as a reminder.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct foo {
+ unsigned int a : 5;
+ unsigned int b : 10;
+ unsigned int c : 1;
+} __attribute__((packed));
+
+int main() {
+ struct foo *a = malloc(sizeof *a);
+
+ a->b = 12; // problem here is that llvm-gcc emits a 4 byte access
+ // which is out of bounds.
+
+ int x = a->b;
+
+ assert(x == 12);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/IsSymbolic.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/IsSymbolic.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/IsSymbolic.c (added)
+++ klee/trunk/test/Feature/IsSymbolic.c Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <assert.h>
+
+int main() {
+ int x, y, z = 0;
+ klee_make_symbolic(&x, sizeof x);
+ klee_make_symbolic(&y, sizeof y);
+ if (x) {
+ assert(klee_is_symbolic(y));
+ } else {
+ assert(!klee_is_symbolic(z));
+ }
+ return 0;
+}
Added: klee/trunk/test/Feature/KleeReportError.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/KleeReportError.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/KleeReportError.c (added)
+++ klee/trunk/test/Feature/KleeReportError.c Wed May 20 23:36:41 2009
@@ -0,0 +1,23 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --emit-all-errors %t2.bc > %t3.log
+// RUN: ls klee-last/ | grep .my.err | wc -l | grep 2
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+ int x, y, *p = 0;
+
+ klee_make_symbolic(&x, sizeof x);
+ klee_make_symbolic(&y, sizeof y);
+
+ if (x)
+ fprintf(stderr, "x\n");
+ else fprintf(stderr, "!x\n");
+
+ if (y) {
+ fprintf(stderr, "My error\n");
+ klee_report_error(__FILE__, __LINE__, "My error", "my.err");
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/LongDoubleSupport.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/LongDoubleSupport.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/LongDoubleSupport.c (added)
+++ klee/trunk/test/Feature/LongDoubleSupport.c Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc > %t2.out
+
+#include <stdio.h>
+#include <float.h>
+
+// FIXME: This doesn't really work at all, it just doesn't
+// crash. Until we have wide constant support, that is all we care
+// about; the only reason this comes up is in initialization of
+// constants, we don't actually end up seeing much code which uses long
+// double.
+int main() {
+ long double a = LDBL_MAX;
+ long double b = -1;
+ long double c = a + b;
+ printf("a = %Lg\n", a);
+ printf("b = %Lg\n", b);
+ printf("c = %Lg\n", c);
+ return 0;
+}
Added: klee/trunk/test/Feature/LowerSwitch.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/LowerSwitch.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/LowerSwitch.c (added)
+++ klee/trunk/test/Feature/LowerSwitch.c Wed May 20 23:36:41 2009
@@ -0,0 +1,30 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t.bc
+// RUN: %klee --exit-on-error --allow-external-sym-calls --switch-type=internal %t.bc
+// RUN: not test -f klee-last/test000010.bout
+// RUN: %klee --exit-on-error --allow-external-sym-calls --switch-type=simple %t.bc
+// RUN: test -f klee-last/test000010.bout
+
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ int c = klee_range(0, 256, "range");
+
+ switch(c) {
+ case 0: printf("0\n"); break;
+ case 10: printf("10\n"); break;
+ case 16: printf("16\n"); break;
+ case 17: printf("17\n"); break;
+ case 18: printf("18\n"); break;
+ case 19: printf("19\n"); break;
+#define C(x) case x: case x+1: case x+2: case x+3
+#define C2(x) C(x): C(x+4): C(x+8): C(x+12)
+#define C3(x) C2(x): C2(x+16): C2(x+32): C2(x+48)
+ C3(128):
+ printf("bignums: %d\n", c); break;
+ default:
+ printf("default\n");
+ break;
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/MakeConcreteSymbolic.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MakeConcreteSymbolic.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MakeConcreteSymbolic.c (added)
+++ klee/trunk/test/Feature/MakeConcreteSymbolic.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+// RUN: grep "done: total queries = 0" klee-last/info
+// RUN: %klee --make-concrete-symbolic=1 --exit-on-error %t1.bc
+// RUN: grep "done: total queries = 2" klee-last/info
+
+
+#include <assert.h>
+
+#define N 2
+int main() {
+ int i;
+ char a;
+
+ a = 10;
+ assert(a == 10);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/MakeSymbolicName.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MakeSymbolicName.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MakeSymbolicName.c (added)
+++ klee/trunk/test/Feature/MakeSymbolicName.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --use-random-search --exit-on-error %t1.bc
+
+#include <assert.h>
+
+int main() {
+ int a[4] = {1, 2, 3, 4};
+ unsigned i;
+
+ klee_make_symbolic_name(&i, sizeof(i), "index");
+ if (i > 3)
+ klee_silent_exit(0);
+
+ assert(a[i] << 1 != 5);
+ if (a[i] << 1 == 6)
+ assert(i == 2);
+}
Added: klee/trunk/test/Feature/MemoryLimit.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MemoryLimit.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MemoryLimit.c (added)
+++ klee/trunk/test/Feature/MemoryLimit.c Wed May 20 23:36:41 2009
@@ -0,0 +1,37 @@
+// RUN: %llvmgcc -DLITTLE_ALLOC -g -c %s -o %t.little.bc
+// RUN: %llvmgcc -g -c %s -o %t.big.bc
+// RUN: %klee --max-memory=20 %t.little.bc > %t.little.log
+// RUN: %klee --max-memory=20 %t.big.bc > %t.big.log
+// RUN: not grep -q "DONE" %t.little.log
+// RUN: not grep -q "DONE" %t.big.log
+
+#include <stdlib.h>
+
+int main() {
+ int i, j, x=0;
+
+#ifdef LITTLE_ALLOC
+ printf("IN LITTLE ALLOC\n");
+
+ // 200 MBs total (in 32 byte chunks)
+ for (i=0; i<100; i++) {
+ for (j=0; j<(1<<16); j++)
+ malloc(1<<5);
+ }
+#else
+ printf("IN BIG ALLOC\n");
+
+ // 200 MBs total
+ for (i=0; i<100; i++) {
+ malloc(1<<21);
+
+ // Ensure we hit the periodic check
+ for (j=0; j<10000; j++)
+ x++;
+ }
+#endif
+
+ printf("DONE!\n");
+
+ return x;
+}
Added: klee/trunk/test/Feature/MultipleFreeResolution.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MultipleFreeResolution.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MultipleFreeResolution.c (added)
+++ klee/trunk/test/Feature/MultipleFreeResolution.c Wed May 20 23:36:41 2009
@@ -0,0 +1,39 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --emit-all-errors %t1.bc
+// RUN: ls klee-last/ | grep .out | wc -l | grep 4
+// RUN: ls klee-last/ | grep .err | wc -l | grep 3
+
+#include <stdlib.h>
+#include <stdio.h>
+
+unsigned klee_urange(unsigned start, unsigned end) {
+ unsigned x;
+ klee_make_symbolic(&x, sizeof x);
+ if (x-start>=end-start) klee_silent_exit(0);
+ return x;
+}
+
+int *make_int(int i) {
+ int *x = malloc(sizeof(*x));
+ *x = i;
+ return x;
+}
+
+int main() {
+ int *buf[4];
+ int i,s;
+
+ for (i=0; i<3; i++)
+ buf[i] = make_int(i);
+ buf[3] = 0;
+
+ s = klee_urange(0,4);
+
+ free(buf[s]);
+
+ for (i=0; i<3; i++) {
+ printf("*buf[%d] = %d\n", i, *buf[i]);
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/MultipleReadResolution.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MultipleReadResolution.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MultipleReadResolution.c (added)
+++ klee/trunk/test/Feature/MultipleReadResolution.c Wed May 20 23:36:41 2009
@@ -0,0 +1,43 @@
+// RUN: echo "x" > %t1.res
+// RUN: echo "x" >> %t1.res
+// RUN: echo "x" >> %t1.res
+// RUN: echo "x" >> %t1.res
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc > %t1.log
+// RUN: diff %t1.res %t1.log
+
+#include <stdio.h>
+
+unsigned klee_urange(unsigned start, unsigned end) {
+ unsigned x;
+ klee_make_symbolic(&x, sizeof x);
+ if (x-start>=end-start) klee_silent_exit(0);
+ return x;
+}
+
+int *make_int(int i) {
+ int *x = malloc(sizeof(*x));
+ *x = i;
+ return x;
+}
+
+int main() {
+ int *buf[4];
+ int i,s,t;
+
+ for (i=0; i<4; i++)
+ buf[i] = make_int((i+1)*2);
+
+ s = klee_urange(0,4);
+
+ int x = *buf[s];
+
+ if (x == 4)
+ if (s!=1)
+ abort();
+
+ printf("x\n");
+ fflush(stdout);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/MultipleReallocResolution.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MultipleReallocResolution.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MultipleReallocResolution.c (added)
+++ klee/trunk/test/Feature/MultipleReallocResolution.c Wed May 20 23:36:41 2009
@@ -0,0 +1,63 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: ls klee-last/ | grep .err | wc -l | grep 2
+// RUN: ls klee-last/ | grep .ptr.err | wc -l | grep 2
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+unsigned klee_urange(unsigned start, unsigned end) {
+ unsigned x;
+ klee_make_symbolic(&x, sizeof x);
+ if (x-start>=end-start) klee_silent_exit(0);
+ return x;
+}
+
+int *make_int(int i, int N) {
+ int *x = malloc(sizeof(*x) * N);
+ *x = i;
+ return x;
+}
+
+int main() {
+ int *buf[4];
+
+ buf[0] = malloc(sizeof(int)*4);
+ buf[1] = malloc(sizeof(int));
+ buf[2] = 0; // gets malloc'd
+ buf[3] = (int*) 0xdeadbeef; // boom
+
+ buf[0][0] = 10;
+ buf[0][1] = 42;
+ buf[1][0] = 20;
+
+ int i = klee_urange(0,4);
+ int new_size = 2 * sizeof(int) * klee_urange(0,2); // 0 or 8
+
+ // whee, party time, needs to:
+ // Fork if size == 0, in which case all buffers get free'd and
+ // we will crash in prints below.
+ // Fork if buf[s] == 0, in which case the buffer gets malloc'd (for s==2)
+ // Fork on other buffers (s in [0,1]) and do realloc
+ // for s==0 this is shrinking
+ // for s==1 this is growing
+ buf[i] = realloc(buf[i], new_size);
+
+ if (new_size == 0) {
+ assert(!buf[2]); // free(0) is a no-op
+ if (i==0) assert(!buf[0] && buf[1]);
+ if (i==1) assert(buf[0] && !buf[1]);
+ assert(i != 3); // we should have crashed on free of invalid
+ } else {
+ assert(new_size == sizeof(int)*2);
+ assert(buf[0][0] == 10);
+ assert(buf[0][1] == 42); // make sure copied
+ assert(buf[1][0] == 20);
+ if (i==1) { int x = buf[1][1]; } // should be safe
+ if (i==2) { int x = buf[2][0]; } // should be safe
+ assert(i != 3); // we should have crashed on realloc of invalid
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/MultipleWriteResolution.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/MultipleWriteResolution.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/MultipleWriteResolution.c (added)
+++ klee/trunk/test/Feature/MultipleWriteResolution.c Wed May 20 23:36:41 2009
@@ -0,0 +1,43 @@
+// RUN: echo "x" > %t1.res
+// RUN: echo "x" >> %t1.res
+// RUN: echo "x" >> %t1.res
+// RUN: echo "x" >> %t1.res
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc > %t1.log
+// RUN: diff %t1.res %t1.log
+
+#include <stdio.h>
+
+unsigned klee_urange(unsigned start, unsigned end) {
+ unsigned x;
+ klee_make_symbolic(&x, sizeof x);
+ if (x-start>=end-start) klee_silent_exit(0);
+ return x;
+}
+
+int *make_int(int i) {
+ int *x = malloc(sizeof(*x));
+ *x = i;
+ return x;
+}
+
+int main() {
+ int *buf[4];
+ int i,s,t;
+
+ for (i=0; i<4; i++)
+ buf[i] = make_int((i+1)*2);
+
+ s = klee_urange(0,4);
+
+ *buf[s] = 5;
+
+ if ((*buf[0] + *buf[1] + *buf[2] + *buf[3]) == 17)
+ if (s!=3)
+ abort();
+
+ printf("x\n");
+ fflush(stdout);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/NamedSeedMatching.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/NamedSeedMatching.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/NamedSeedMatching.c (added)
+++ klee/trunk/test/Feature/NamedSeedMatching.c Wed May 20 23:36:41 2009
@@ -0,0 +1,41 @@
+// RUN: %llvmgcc -c -g %s -o %t.bc
+// RUN: rm -rf %t.out
+// RUN: %klee --output-dir=%t.out %t.bc "initial"
+// RUN: test -f %t.out/test000001.bout
+// RUN: not test -f %t.out/test000002.bout
+// RUN: %klee --only-replay-seeds --named-seed-matching --seed-out %t.out/test000001.bout %t.bc > %t.log
+// RUN: grep -q "a==3" %t.log
+// RUN: grep -q "b==4" %t.log
+// RUN: grep -q "c==5" %t.log
+// RUN: grep -q "x==6" %t.log
+
+#include <string.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ int a, b, c, x;
+
+ if (argc==2 && strcmp(argv[1], "initial") == 0) {
+ klee_make_symbolic_name(&a, sizeof a, "a");
+ klee_make_symbolic_name(&b, sizeof b, "b");
+ klee_make_symbolic_name(&c, sizeof c, "c");
+ klee_make_symbolic_name(&x, sizeof x, "a");
+
+ klee_assume(a == 3);
+ klee_assume(b == 4);
+ klee_assume(c == 5);
+ klee_assume(x == 6);
+ } else {
+ klee_make_symbolic_name(&a, sizeof a, "a");
+ klee_make_symbolic_name(&c, sizeof c, "c");
+ klee_make_symbolic_name(&b, sizeof b, "b");
+ klee_make_symbolic_name(&x, sizeof x, "a");
+ }
+
+ if (a==3) printf("a==3\n");
+ if (b==4) printf("b==4\n");
+ if (c==5) printf("c==5\n");
+ if (x==6) printf("x==6\n");
+
+ return 0;
+}
Added: klee/trunk/test/Feature/OneFreeError.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/OneFreeError.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/OneFreeError.c (added)
+++ klee/trunk/test/Feature/OneFreeError.c Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.ptr.err
+
+int main() {
+ int *x = malloc(4);
+ free(x);
+ x[0] = 1;
+ return 0;
+}
Added: klee/trunk/test/Feature/OneOutOfBounds.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/OneOutOfBounds.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/OneOutOfBounds.c (added)
+++ klee/trunk/test/Feature/OneOutOfBounds.c Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.ptr.err
+
+int main() {
+ int *x = malloc(4);
+ x[1] = 1;
+ free(x);
+ return 0;
+}
Added: klee/trunk/test/Feature/Optimize.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/Optimize.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/Optimize.c (added)
+++ klee/trunk/test/Feature/Optimize.c Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+// RUN: %llvmgcc %s --emit-llvm -O0 -c -o %t2.bc
+// RUN: rm -f %t2.log
+// RUN: %klee --stop-after-n-instructions=100 --optimize %t2.bc > %t3.log
+// RUN: echo "good" > %t3.good
+// RUN: diff %t3.log %t3.good
+
+// should complete by 100 instructions if opt is on
+
+int main() {
+ int i, res = 0;
+
+ for (i=1; i<=1000; i++)
+ res += i;
+
+ if (res == (1000*1001)/2) {
+ printf("good\n");
+ } else {
+ printf("bad\n");
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/OverlappedError.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/OverlappedError.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/OverlappedError.c (added)
+++ klee/trunk/test/Feature/OverlappedError.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+// RUN: %llvmgcc %s -g -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: ls klee-last/ | grep .out | wc -l | grep 4
+// RUN: ls klee-last/ | grep .ptr.err | wc -l | grep 2
+
+#include <stdlib.h>
+
+int main() {
+ if (klee_range(0,2, "range")) {
+ char *x = malloc(8);
+ *((int*) &x[klee_range(0,6, "range")]) = 1;
+ free(x);
+ } else {
+ char *x = malloc(8);
+ *((int*) &x[klee_range(-1,5, "range")]) = 1;
+ free(x);
+ }
+ return 0;
+}
Added: klee/trunk/test/Feature/PreferCex.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/PreferCex.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/PreferCex.c (added)
+++ klee/trunk/test/Feature/PreferCex.c Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+// RUN: klee-bout-tool klee-last/test000001.bout | grep -F 'Hi\x00\x00'
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main() {
+ char buf[4];
+
+ klee_make_symbolic(buf, sizeof buf);
+ klee_prefer_cex(buf, buf[0]=='H');
+ klee_prefer_cex(buf, buf[1]=='i');
+ klee_prefer_cex(buf, buf[2]=='\0');
+
+ return 0;
+}
Added: klee/trunk/test/Feature/RaiseAsm.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/RaiseAsm.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/RaiseAsm.c (added)
+++ klee/trunk/test/Feature/RaiseAsm.c Wed May 20 23:36:41 2009
@@ -0,0 +1,39 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <assert.h>
+
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+uint16 byteswap_uint16(uint16 x) {
+ return (x << 8) | (x >> 8);
+}
+uint32 byteswap_uint32(uint32 x) {
+ return ((byteswap_uint16(x) << 16) |
+ (byteswap_uint16(x >> 16)));
+}
+
+uint16 byteswap_uint16_asm(uint16 x) {
+ uint16 res;
+ __asm__("rorw $8, %w0" : "=r" (res) : "0" (x) : "cc");
+ return res;
+}
+
+uint32 byteswap_uint32_asm(uint32 x) {
+ uint32 res;
+ __asm__("rorw $8, %w0;"
+ "rorl $16, %0;"
+ "rorw $8, %w0" : "=r" (res) : "0" (x) : "cc");
+ return res;
+}
+
+int main() {
+ uint16 ui16 = klee_int("ui16");
+ uint32 ui32 = klee_int("ui32");
+
+ assert(ui16 == byteswap_uint16(byteswap_uint16_asm(ui16)));
+ assert(ui32 == byteswap_uint32(byteswap_uint32_asm(ui32)));
+
+ return 0;
+}
Added: klee/trunk/test/Feature/ReallocFailure.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/ReallocFailure.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/ReallocFailure.c (added)
+++ klee/trunk/test/Feature/ReallocFailure.c Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+int main() {
+ int *p = malloc(sizeof(int)*2);
+ assert(p);
+ p[1] = 52;
+
+ int *p2 = realloc(p, 1<<30);
+ assert(p2 == 0);
+ assert(p[1] == 52);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/ReplayPath.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/ReplayPath.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/ReplayPath.c (added)
+++ klee/trunk/test/Feature/ReplayPath.c Wed May 20 23:36:41 2009
@@ -0,0 +1,27 @@
+// RUN: echo "1" > %t1.path
+// RUN: echo "0" >> %t1.path
+// RUN: echo "1" >> %t1.path
+// RUN: echo "0" >> %t1.path
+// RUN: echo "1" >> %t1.path
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --replay-path %t1.path %t2.bc > %t3.log
+// RUN: echo "res: 110" > %t3.good
+// RUN: diff %t3.log %t3.good
+
+int main() {
+ int res = 1;
+ int x;
+
+ klee_make_symbolic(&x, sizeof x);
+
+ if (x&1) res *= 2;
+ if (x&2) res *= 3;
+ if (x&4) res *= 5;
+
+ // get forced branch coverage
+ if (x&2) res *= 7;
+ if (!(x&2)) res *= 11;
+ printf("res: %d\n", res);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/Searchers.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/Searchers.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/Searchers.c (added)
+++ klee/trunk/test/Feature/Searchers.c Wed May 20 23:36:41 2009
@@ -0,0 +1,52 @@
+// RUN: %llvmgcc %s --emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee %t2.bc
+// RUN: %klee --use-random-search %t2.bc
+// RUN: %klee --use-non-uniform-random-search %t2.bc
+// RUN: %klee --use-non-uniform-random-search --weight-type=query-cost %t2.bc
+// RUN: %klee --use-batching-search %t2.bc
+// RUN: %klee --use-batching-search --use-random-search %t2.bc
+// RUN: %klee --use-batching-search --use-non-uniform-random-search %t2.bc
+// RUN: %klee --use-batching-search --use-non-uniform-random-search --weight-type=query-cost %t2.bc
+// RUN: %klee --use-merge --debug-log-merge --debug-log-state-merge %t2.bc
+// RUN: %klee --use-merge --use-batching-search %t2.bc
+// RUN: %klee --use-merge --use-batching-search --use-random-search %t2.bc
+// RUN: %klee --use-merge --use-batching-search --use-non-uniform-random-search %t2.bc
+// RUN: %klee --use-merge --use-batching-search --use-non-uniform-random-search --weight-type=query-cost %t2.bc
+// RUN: %klee --use-iterative-deepening-time-search --use-batching-search %t2.bc
+// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --use-random-search %t2.bc
+// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --use-non-uniform-random-search %t2.bc
+// RUN: %klee --use-iterative-deepening-time-search --use-batching-search --use-non-uniform-random-search --weight-type=query-cost %t2.bc
+
+
+/* this test is basically just for coverage and doesn't really do any
+ correctness check (aside from testing that the various combinations
+ don't crash) */
+
+int validate(char *buf, int N) {
+
+ int i;
+
+ for (i=0; i<N; i++) {
+ if (buf[i]==0) {
+ klee_merge();
+ return 0;
+ }
+ }
+
+ klee_merge();
+ return 1;
+}
+
+#ifndef SYMBOLIC_SIZE
+#define SYMBOLIC_SIZE 15
+#endif
+int main(int argc, char **argv) {
+ int N = SYMBOLIC_SIZE;
+ unsigned char *buf = malloc(N);
+ int i;
+
+ klee_make_symbolic(buf, N);
+ if (validate(buf, N))
+ return buf[0];
+ return 0;
+}
Added: klee/trunk/test/Feature/SetForking.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/SetForking.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/SetForking.c (added)
+++ klee/trunk/test/Feature/SetForking.c Wed May 20 23:36:41 2009
@@ -0,0 +1,28 @@
+// RUN: %llvmgcc -g -c %s -o %t.bc
+// RUN: %klee %t.bc > %t.log
+// RUN: sort %t.log | uniq -c > %t.uniq.log
+// RUN: grep "1 A" %t.uniq.log
+// RUN: grep "1 B" %t.uniq.log
+// RUN: grep "1 C" %t.uniq.log
+
+#include <stdio.h>
+
+int main() {
+ klee_set_forking(0);
+
+ if (klee_range(0, 2, "range")) {
+ printf("A\n");
+ } else {
+ printf("A\n");
+ }
+
+ klee_set_forking(1);
+
+ if (klee_range(0, 2, "range")) {
+ printf("B\n");
+ } else {
+ printf("C\n");
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/Vararg.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/Vararg.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/Vararg.c (added)
+++ klee/trunk/test/Feature/Vararg.c Wed May 20 23:36:41 2009
@@ -0,0 +1,82 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc > %t2.out
+// RUN: grep "types: (52, 37, 2.00, (9,12,15))" %t2.out
+// RUN: test -f klee-last/test000001.ptr.err
+
+#include <stdarg.h>
+#include <assert.h>
+#include <stdio.h>
+
+struct triple {
+ int first, second, third;
+};
+
+int test1(int x, ...) {
+ va_list ap;
+ va_start(ap, x);
+ int i32 = va_arg(ap, int);
+ long long i64 = va_arg(ap, long long);
+ double d = va_arg(ap, double);
+ struct triple p = va_arg(ap, struct triple);
+ printf("types: (%d, %lld, %.2f, (%d,%d,%d))\n", i32, i64, d, p.first, p.second, p.third);
+ va_end(ap);
+}
+
+int sum(int N, ...) {
+ int i, res = 0;
+ va_list ap,ap2;
+
+ va_start(ap, N);
+ for (i=0; i<N; i++) {
+ if (i==1)
+ va_copy(ap2, ap);
+ res += va_arg(ap, int);
+ }
+ for (i=0; i<N-1; i++)
+ res += va_arg(ap2, int);
+ va_end(ap);
+
+ return res;
+}
+
+// test using aps in an array (no multiple resolution
+// testing, though)
+int va_array(int N, ...) {
+ va_list aps[2];
+ unsigned i;
+ unsigned sum1 = 0, sum2 = 0;
+
+ for (i=0; i<2; i++)
+ va_start(aps[i], N);
+
+ for (i=0; i<N; i++) {
+ unsigned cmd = va_arg(aps[0], int);
+
+ if (cmd==0) {
+ sum1 += va_arg(aps[0],int);
+ } else if (cmd==1) {
+ sum2 += va_arg(aps[1],int);
+ } else if (cmd==2) {
+ va_copy(aps[1], aps[0]);
+ }
+ }
+
+ for (i=0; i<2; i++)
+ va_end(aps[i]);
+
+ return 3*sum1 + 5*sum2;
+}
+
+int main() {
+ struct triple p = { 9, 12, 15 };
+ test1(-1, 52, 37ll, 2.0, p);
+
+ assert(sum(2, 3, 4) == 11);
+ assert(sum(0) == 0);
+ assert(va_array(5, 0, 5, 1, 1, 2, 1)==45); // 15 + 30
+
+ // should give memory error
+ test1(-1, 52, 37, 2.0, p);
+
+ return 0;
+}
Added: klee/trunk/test/Feature/WithLibc.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/WithLibc.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/WithLibc.c (added)
+++ klee/trunk/test/Feature/WithLibc.c Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --libc=klee %t2.bc > %t3.log
+// RUN: echo "good" > %t3.good
+// RUN: diff %t3.log %t3.good
+
+int main() {
+ char buf[4];
+ char *s = "foo";
+
+ klee_make_symbolic(buf, sizeof buf);
+ buf[3] = 0;
+
+ if (strcmp(buf, s)==0) {
+ if (buf[0]=='f' && buf[1]=='o' && buf[2]=='o' && buf[3]==0) {
+ printf("good\n");
+ } else {
+ printf("bad\n");
+ }
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Feature/WriteCov.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/WriteCov.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/WriteCov.c (added)
+++ klee/trunk/test/Feature/WriteCov.c Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t2.bc
+// RUN: %klee --exit-on-error --write-cov %t2.bc
+// RUN: grep WriteCov.c:10 klee-last/test000002.cov
+// RUN: grep WriteCov.c:12 klee-last/test000001.cov
+
+#include <assert.h>
+
+int main() {
+ if (klee_range(0,2, "range")) {
+ assert(__LINE__ == 10); printf("__LINE__ = %d\n", __LINE__);
+ } else {
+ assert(__LINE__ == 12); printf("__LINE__ = %d\n", __LINE__);
+ }
+ return 0;
+}
Added: klee/trunk/test/Feature/_utils._ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/_utils._ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/_utils._ll (added)
+++ klee/trunk/test/Feature/_utils._ll Wed May 20 23:36:41 2009
@@ -0,0 +1,71 @@
+define i32 @util_make_and_i1(i32 %a, i32 %b) {
+ %a_i1 = icmp ne i32 %a, 0
+ %b_i1 = icmp ne i32 %b, 0
+ %res_i1 = and i1 %a_i1, %b_i1
+ %res = zext i1 %res_i1 to i32
+ ret i32 %res
+}
+
+define i32 @util_make_or_i1(i32 %a, i32 %b) {
+ %a_i1 = icmp ne i32 %a, 0
+ %b_i1 = icmp ne i32 %b, 0
+ %res_i1 = or i1 %a_i1, %b_i1
+ %res = zext i1 %res_i1 to i32
+ ret i32 %res
+}
+
+define i16 @util_make_concat2(i8 %a, i8 %b) {
+ %tmp = alloca i16
+ %tmp8 = bitcast i16* %tmp to i8*
+ %p0 = getelementptr i8* %tmp8, i32 0
+ %p1 = getelementptr i8* %tmp8, i32 1
+ store i8 %b, i8* %p0
+ store i8 %a, i8* %p1
+ %concat = load i16* %tmp
+ ret i16 %concat
+}
+
+define i32 @util_make_concat4(i8 %a, i8 %b, i8 %c, i8 %d) {
+ %tmp = alloca i32
+ %tmp8 = bitcast i32* %tmp to i8*
+ %p0 = getelementptr i8* %tmp8, i32 0
+ %p1 = getelementptr i8* %tmp8, i32 1
+ %p2 = getelementptr i8* %tmp8, i32 2
+ %p3 = getelementptr i8* %tmp8, i32 3
+ store i8 %d, i8* %p0
+ store i8 %c, i8* %p1
+ store i8 %b, i8* %p2
+ store i8 %a, i8* %p3
+ %concat = load i32* %tmp
+ ret i32 %concat
+}
+
+define i64 @util_make_concat8(i8 %a, i8 %b, i8 %c, i8 %d,
+ i8 %e, i8 %f, i8 %g, i8 %h) {
+ %tmp = alloca i64
+ %tmp8 = bitcast i64* %tmp to i8*
+ %p0 = getelementptr i8* %tmp8, i32 0
+ %p1 = getelementptr i8* %tmp8, i32 1
+ %p2 = getelementptr i8* %tmp8, i32 2
+ %p3 = getelementptr i8* %tmp8, i32 3
+ %p4 = getelementptr i8* %tmp8, i32 4
+ %p5 = getelementptr i8* %tmp8, i32 5
+ %p6 = getelementptr i8* %tmp8, i32 6
+ %p7 = getelementptr i8* %tmp8, i32 7
+ store i8 %h, i8* %p0
+ store i8 %g, i8* %p1
+ store i8 %f, i8* %p2
+ store i8 %e, i8* %p3
+ store i8 %d, i8* %p4
+ store i8 %c, i8* %p5
+ store i8 %b, i8* %p6
+ store i8 %a, i8* %p7
+ %concat = load i64* %tmp
+ ret i64 %concat
+}
+
+define i32 @util_make_select(i32 %cond, i32 %t, i32 %f) {
+ %cond_i1 = icmp ne i32 %cond, 0
+ %res = select i1 %cond_i1, i32 %t, i32 %f
+ ret i32 %res
+}
\ No newline at end of file
Added: klee/trunk/test/Feature/const_array_opt1.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/const_array_opt1.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/const_array_opt1.c (added)
+++ klee/trunk/test/Feature/const_array_opt1.c Wed May 20 23:36:41 2009
@@ -0,0 +1,37 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --const-array-opt --max-time=10 --only-output-states-covering-new %t.bc >%t.log
+// grep -q "Finished successfully!\n"
+
+/* This is testing the const array optimization. On my 2.3GHz machine
+ this takes under 2 seconds w/ the optimization and almost 6 minutes
+ w/o. So we kill it in 10 sec and check if it has finished
+ successfully. */
+
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+
+int main() {
+#define N 8192
+#define N_IDX 16
+ unsigned char a[N];
+ unsigned i, k[N_IDX];
+
+ for (i=0; i<N; i++)
+ a[i] = i % 256;
+
+ klee_make_symbolic_name(k, sizeof(k), "k");
+
+ for (i=0; i<N_IDX; i++) {
+ if (k[i] >= N)
+ klee_silent_exit(0);
+
+ if (a[k[i]] == i)
+ assert(k[i] % 256 == i);
+ else klee_silent_exit(0);
+ }
+
+ printf("Finished successfully!\n");
+
+ return 0;
+}
Added: klee/trunk/test/Feature/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/dg.exp (added)
+++ klee/trunk/test/Feature/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
Added: klee/trunk/test/Feature/utils.h
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Feature/utils.h?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Feature/utils.h (added)
+++ klee/trunk/test/Feature/utils.h Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+uint32_t util_make_and_i1(uint32_t a, uint32_t b);
+uint32_t util_make_or_i1(uint32_t a, uint32_t b);
+
+uint16_t util_make_concat2(uint8_t a, uint8_t b);
+uint32_t util_make_concat4(uint8_t a, uint8_t b,
+ uint8_t c, uint8_t d);
+uint64_t util_make_concat8(uint8_t a, uint8_t b,
+ uint8_t c, uint8_t d,
+ uint8_t e, uint8_t f,
+ uint8_t g, uint8_t h);
+uint32_t util_make_select(uint32_t cond, uint32_t true, uint32_t false);
Added: klee/trunk/test/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Makefile (added)
+++ klee/trunk/test/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,101 @@
+#===- test/Makefile ----------------------------------------*- Makefile -*--===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file was developed by the LLVM research group and is distributed under
+# the University of Illinois Open Source License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+LEVEL = ..
+DIRS =
+
+#
+# Make Dejagnu the default for testing
+#
+all:: check-local
+
+# Include other test rules
+include Makefile.tests
+
+#===------------------------------------------------------------------------===#
+# DejaGNU testing support
+#===------------------------------------------------------------------------===#
+
+ifdef TESTSUITE
+CLEANED_TESTSUITE := $(patsubst %/,%,$(TESTSUITE))
+CLEANED_TESTSUITE := $(patsubst test/%,%,$(CLEANED_TESTSUITE))
+RUNTESTFLAGS := --tool $(CLEANED_TESTSUITE)
+endif
+
+ifneq ($(RUNTEST),)
+check-local:: site.exp
+ ( ulimit -t 600 ; ulimit -d 512000 ; \
+ PATH="$(ToolDir):$(LLVMToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$(PATH)" \
+ $(RUNTEST) $(RUNTESTFLAGS) ; \
+ ! grep FAIL testrun.log )
+else
+check-local:: site.exp
+ @echo "*** dejagnu not found. Make sure runtest is in your PATH, then reconfigure llvm."
+endif
+
+ifdef TESTONE
+CLEANED_TESTONE := $(patsubst %/,%,$(TESTONE))
+CLEANED_TESTONE := $(patsubst test/%,%,$(CLEANED_TESTONE))
+SUBDIR := $(shell dirname $(CLEANED_TESTONE))
+TESTPATH := $(PROJ_SRC_ROOT)/test/$(CLEANED_TESTONE)
+check-one: site.exp $(TCLSH)
+ $(Verb)( echo "source $(PROJ_OBJ_ROOT)/test/site.exp" ; \
+ echo "set subdir $(SUBDIR)" ; \
+ echo "proc pass { msg } { puts \"PASS: \$$msg\" } "; \
+ echo "proc fail { msg } { puts \"FAIL: \$$msg\" }" ; \
+ echo "proc xfail { msg } { puts \"XFAIL: \$$msg\" }" ; \
+ echo "proc xpass { msg } { puts \"XPASS: \$$msg\" }" ; \
+ echo "source $(PROJ_SRC_ROOT)/test/lib/llvm.exp" ; \
+ echo "RunLLVMTests $(TESTPATH)" ) | \
+ ( ulimit -t 600 ; ulimit -d 512000 ; \
+ PATH="$(ToolDir):$(LLVMToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$(PATH)" \
+ $(TCLSH) )
+endif
+
+clean::
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name Output -type d -print`
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name 'ft-out*' -type d -print`
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name 'ft-last' -print`
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name 'klee-last'`
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name 'klee-out*'`
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name '*~'`
+ $(RM) -rf `find $(PROJ_OBJ_ROOT)/test -name test.log`
+ rm -f site.exp
+
+site.exp: Makefile $(LEVEL)/Makefile.config
+ @echo 'Making a new site.exp file...'
+ @echo '## these variables are automatically generated by make ##' >site.tmp
+ @echo '# Do not edit here. If you wish to override these values' >>site.tmp
+ @echo '# edit the last section' >>site.tmp
+ @echo 'set target_triplet "$(TARGET_TRIPLE)"' >> site.tmp
+ @echo 'set ENABLE_UCLIBC "$(ENABLE_UCLIBC)"' >> site.tmp
+ @echo 'set ENABLE_POSIX_RUNTIME "$(ENABLE_POSIX_RUNTIME)"' >> site.tmp
+ @echo 'set TEST_FEATURE_LIST "$(TEST_FEATURE_LIST)"' >> site.tmp
+ @echo 'set prcontext "$(TCLSH) $(LLVM_SRC_ROOT)/test/Scripts/prcontext.tcl"' >> site.tmp
+ @echo 'set llvmtoolsdir "$(ToolDir)"' >>site.tmp
+ @echo 'set llvmlibsdir "$(LibDir)"' >>site.tmp
+ @echo 'set srcroot "$(PROJ_SRC_ROOT)"' >>site.tmp
+ @echo 'set objroot "$(PROJ_OBJ_ROOT)"' >>site.tmp
+ @echo 'set srcdir "$(PROJ_SRC_ROOT)/test"' >>site.tmp
+ @echo 'set objdir "$(PROJ_OBJ_ROOT)/test"' >>site.tmp
+ @echo 'set gccpath "$(CC)"' >>site.tmp
+ @echo 'set gxxpath "$(CXX)"' >>site.tmp
+ @echo 'set compile_c "$(CC) $(CPP.Flags) $(C.Flags) $(CompileCommonOpts) -c "' >>site.tmp
+ @echo 'set compile_cxx "$(CXX) $(CPP.Flags) $(CXX.Flags) $(CompileCommonOpts) - c"' >> site.tmp
+ @echo 'set link "$(CXX) $(CPP.Flags) $(CXX.Flags) $(CompileCommonOpts) $(LD.Flags)"' >>site.tmp
+ @echo 'set llvmgcc "$(LLVMGCC)"' >> site.tmp
+ @echo 'set llvmgxx "$(LLVMGCC)"' >> site.tmp
+ @echo 'set llvmgccmajvers "$(LLVMGCC_MAJVERS)"' >> site.tmp
+ @echo 'set shlibext "$(SHLIBEXT)"' >> site.tmp
+ @echo '## All variables above are generated by configure. Do Not Edit ## ' >>site.tmp
+ @test ! -f site.exp || \
+ sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp
+ @-rm -f site.bak
+ @test ! -f site.exp || mv site.exp site.bak
+ @mv site.tmp site.exp
Added: klee/trunk/test/Makefile.tests
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Makefile.tests?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Makefile.tests (added)
+++ klee/trunk/test/Makefile.tests Wed May 20 23:36:41 2009
@@ -0,0 +1,80 @@
+##----------------------------------------------------------*- Makefile -*-===##
+##
+## Common rules for generating, linking, and compiling via LLVM. This is
+## used to implement a robust testing framework for LLVM
+##
+##-------------------------------------------------------------------------===##
+
+# If the user specified a TEST= option on the command line, we do not want to do
+# the default testing type. Instead, we change the default target to be the
+# test:: target.
+#
+ifdef TEST
+test::
+endif
+
+# We do not want to make .d files for tests!
+DISABLE_AUTO_DEPENDENCIES=1
+
+include ${LEVEL}/Makefile.common
+
+# Specify ENABLE_STATS on the command line to enable -stats and -time-passes
+# output from gccas and gccld.
+ifdef ENABLE_STATS
+STATS = -stats -time-passes
+endif
+
+.PHONY: clean default
+
+# These files, which might be intermediate results, should not be deleted by
+# make
+.PRECIOUS: Output/%.bc Output/%.ll
+.PRECIOUS: Output/%.tbc Output/%.tll
+.PRECIOUS: Output/.dir
+.PRECIOUS: Output/%.llvm.bc
+.PRECIOUS: Output/%.llvm
+
+LCCFLAGS += -O2 -Wall
+LCXXFLAGS += -O2 -Wall
+LLCFLAGS =
+TESTRUNR = @echo Running test: $<; \
+ PATH="$(LLVMTOOLCURRENT):$(LLVM_SRC_ROOT)/test/Scripts:$(PATH)" \
+ $(LLVM_SRC_ROOT)/test/TestRunner.sh
+
+LLCLIBS := $(LLCLIBS) -lm
+
+clean::
+ $(RM) -f a.out core
+ $(RM) -rf Output/
+
+# Compile from X.c to Output/X.ll
+Output/%.ll: %.c $(LCC1) Output/.dir $(INCLUDES)
+ -$(LLVMGCCWITHPATH) $(CPPFLAGS) $(LCCFLAGS) -S $< -o $@
+
+# Compile from X.cpp to Output/X.ll
+Output/%.ll: %.cpp $(LCC1XX) Output/.dir $(INCLUDES)
+ -$(LLVMGXXWITHPATH) $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@
+
+# Compile from X.cc to Output/X.ll
+Output/%.ll: %.cc $(LCC1XX) Output/.dir $(INCLUDES)
+ -$(LLVMGXXWITHPATH) $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@
+
+# LLVM Assemble from Output/X.ll to Output/X.bc. Output/X.ll must have come
+# from GCC output, so use GCCAS.
+#
+Output/%.bc: Output/%.ll $(LGCCAS)
+ -$(LGCCAS) $(STATS) $< -o $@
+
+# LLVM Assemble from X.ll to Output/X.bc. Because we are coming directly from
+# LLVM source, use the non-transforming assembler.
+#
+Output/%.bc: %.ll $(LLVMAS) Output/.dir
+ -$(LLVMAS) -f $< -o $@
+
+## Cancel built-in implicit rules that override above rules
+%: %.s
+
+%: %.c
+
+%.o: %.c
+
Added: klee/trunk/test/README
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/README?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/README (added)
+++ klee/trunk/test/README Wed May 20 23:36:41 2009
@@ -0,0 +1 @@
+about tests....
Added: klee/trunk/test/Runtime/POSIX/DirConsistency.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/DirConsistency.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/DirConsistency.c (added)
+++ klee/trunk/test/Runtime/POSIX/DirConsistency.c Wed May 20 23:36:41 2009
@@ -0,0 +1,64 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --run-in=/tmp --use-random-search --init-env --libc=uclibc --posix-runtime --exit-on-error %t.bc --sym-files 1 1 > %t1.log
+// RUN: %llvmgcc -D_FILE_OFFSET_BITS=64 %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --run-in=/tmp --use-random-search --init-env --libc=uclibc --posix-runtime --exit-on-error %t.bc --sym-files 1 1 > %t2.log
+// RUN: sort %t1.log %t2.log | uniq -c > %t3.log
+// RUN: grep -q "4 COUNT" %t3.log
+
+// For this test really to work as intended it needs to be run in a
+// directory large enough to cause uclibc to do multiple getdents
+// calls (otherwise uclibc will handle the seeks itself). We should
+// create a bunch of files or something.
+//
+// It is even more important for this test because it requires the
+// directory not to change while running, which might be a lot to
+// demand of /tmp.
+
+#define _LARGEFILE64_SOURCE
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int main(int argc, char **argv) {
+ struct stat s;
+ int res = stat("A", &s);
+ int hasA = !(res!=0 && errno==ENOENT);
+
+ //printf("sizeof(dirent) = %d\n", sizeof(struct dirent));
+ //printf("sizeof(dirent64) = %d\n", sizeof(struct dirent64));
+
+ //printf("\"A\" exists: %d\n", hasA);
+
+ DIR *d = opendir(".");
+ assert(d);
+
+ int snum = 1;
+ if (klee_range(0,2,"range")) {
+ snum = 2;
+ printf("state%d\n", snum);
+ }
+
+ int foundA = 0, count = 0;
+ struct dirent *de;
+ while ((de = readdir(d))) {
+ // printf("state%d: dirent: %s\n", snum, de->d_name);
+ if (strcmp(de->d_name, "A") == 0)
+ foundA = 1;
+ count++;
+ }
+
+ closedir(d);
+
+ //printf("found A: %d\n", foundA);
+
+ // Ensure atomic write
+ char buf[64];
+ sprintf(buf, "COUNT: %d\n", count);
+ fputs(buf, stdout);
+ assert(hasA == foundA);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/DirSeek.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/DirSeek.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/DirSeek.c (added)
+++ klee/trunk/test/Runtime/POSIX/DirSeek.c Wed May 20 23:36:41 2009
@@ -0,0 +1,57 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --run-in=/tmp --init-env --libc=uclibc --posix-runtime --exit-on-error %t2.bc --sym-files 2 2
+// RUN: %klee --run-in=/tmp --init-env --libc=uclibc --posix-runtime --exit-on-error %t2.bc --sym-files 1 2
+// RUN: %klee --run-in=/tmp --init-env --libc=uclibc --posix-runtime --exit-on-error %t2.bc --sym-files 0 2
+
+// For this test really to work as intended it needs to be run in a
+// directory large enough to cause uclibc to do multiple getdents
+// calls (otherwise uclibc will handle the seeks itself). We should
+// create a bunch of files or something.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+ struct stat s;
+
+ char first[256], second[256];
+ DIR *d = opendir(".");
+ struct dirent *de = readdir(d);
+ assert(de);
+ strcpy(first, de->d_name);
+ off_t pos = telldir(d);
+ printf("pos: %d\n", telldir(d));
+ de = readdir(d);
+ assert(de);
+ strcpy(second, de->d_name);
+
+ // Go back to second and check
+ seekdir(d, pos);
+ de = readdir(d);
+ assert(de);
+ assert(strcmp(de->d_name, second) == 0);
+
+ // Go to end, then back to 2nd
+ while (de)
+ de = readdir(d);
+ assert(!errno);
+ seekdir(d, pos);
+ assert(telldir(d) == pos);
+ de = readdir(d);
+ assert(de);
+ assert(strcmp(de->d_name, second) == 0);
+
+ // Go to beginning and check
+ rewinddir(d);
+ de = readdir(d);
+ assert(de);
+ assert(strcmp(de->d_name, first) == 0);
+ closedir(d);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/FDNumbers.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/FDNumbers.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/FDNumbers.c (added)
+++ klee/trunk/test/Runtime/POSIX/FDNumbers.c Wed May 20 23:36:41 2009
@@ -0,0 +1,24 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --init-env --posix-runtime --exit-on-error %t2.bc --sym-files 1 10
+
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int main(int argc, char **argv) {
+ int fd = open("A", O_TRUNC);
+ assert(fd == 3);
+ assert(!close(0));
+ assert(!close(1));
+ assert(close(0) == -1);
+ assert(close(1) == -1);
+ assert(open("A", O_TRUNC) == 0);
+ assert(dup(0) == 1);
+ assert(open("A", O_TRUNC) == 4);
+ assert(!close(1));
+ assert(open("A", O_TRUNC) == 1);
+ assert(dup(0) != 1);
+ assert(dup2(0,1) == 1);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/FD_Fail.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/FD_Fail.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/FD_Fail.c (added)
+++ klee/trunk/test/Runtime/POSIX/FD_Fail.c Wed May 20 23:36:41 2009
@@ -0,0 +1,25 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --libc=uclibc --posix-runtime --init-env %t1.bc --sym-files 0 0 --max-fail 1 > %t.log
+// RUN: grep -q "fread(): ok" %t.log
+// RUN: grep -q "fread(): fail" %t.log
+// RUN: grep -q "fclose(): ok" %t.log
+// RUN: grep -q "fclose(): fail" %t.log
+
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+ char buf[1024];
+ FILE* f = fopen("/etc/fstab", "r");
+ assert(f);
+
+ int r = fread(buf, 1, 100, f);
+ printf("fread(): %s\n",
+ r ? "ok" : "fail");
+
+ r = fclose(f);
+ printf("fclose(): %s\n",
+ r ? "ok" : "fail");
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/FD_Fail2.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/FD_Fail2.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/FD_Fail2.c (added)
+++ klee/trunk/test/Runtime/POSIX/FD_Fail2.c Wed May 20 23:36:41 2009
@@ -0,0 +1,34 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --libc=uclibc --posix-runtime --init-env %t1.bc --sym-files 0 0 --max-fail 1
+// RUN: test -f klee-last/test000001.bout
+// RUN: test -f klee-last/test000002.bout
+// RUN: test -f klee-last/test000003.bout
+// RUN: test -f klee-last/test000004.bout
+// RUN: test -f klee-last/test000005.bout
+// RUN: test -f klee-last/test000006.bout
+// RUN: test -f klee-last/test000007.bout
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, char** argv) {
+ char buf[1024];
+ int fd = open("/etc/fstab", O_RDONLY);
+ assert(fd != -1);
+
+ int r = read(fd, buf, 1, 100);
+ if (r != -1)
+ printf("read() succeeded\n");
+ else printf("read() failed with errno %s\n", strerror(errno));
+
+ r = close(fd);
+ if (r != -1)
+ printf("close() succeeded\n");
+ else printf("close() failed with errno %s\n", strerror(errno));
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Fcntl.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Fcntl.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Fcntl.c (added)
+++ klee/trunk/test/Runtime/POSIX/Fcntl.c Wed May 20 23:36:41 2009
@@ -0,0 +1,17 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --init-env --posix-runtime --exit-on-error %t2.bc --sym-files 1 10
+
+#include <assert.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv) {
+ int fd = open("A", O_RDWR|O_TRUNC);
+ if (fd == -1)
+ klee_silent_exit(0);
+ assert(fd == 3);
+ assert((fcntl(fd, F_GETFD) & FD_CLOEXEC) == 0);
+ assert(fcntl(fd, F_SETFD, FD_CLOEXEC, 1) == 0);
+ assert((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/FilePerm.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/FilePerm.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/FilePerm.c (added)
+++ klee/trunk/test/Runtime/POSIX/FilePerm.c Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --posix-runtime --init-env %t.bc --sym-files 1 10 --sym-stdout 2>%t.log
+// RUN: test -f klee-last/test000001.bout
+// RUN: test -f klee-last/test000002.bout
+// RUN: test -f klee-last/test000003.bout
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+int main(int argc, char** argv) {
+ int fd = open("A", O_RDWR);
+ if (fd != -1)
+ fprintf(stderr, "File 'A' opened successfully\n");
+ else fprintf(stderr, "Cannot open file 'A'\n");
+
+ if (fd != -1)
+ close(fd);
+}
Added: klee/trunk/test/Runtime/POSIX/FreeArgv.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/FreeArgv.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/FreeArgv.c (added)
+++ klee/trunk/test/Runtime/POSIX/FreeArgv.c Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --init-env --posix-runtime %t.bc --sym-args 1 1 1
+// RUN: test -f klee-last/test000001.free.err
+// RUN: test -f klee-last/test000002.free.err
+// RUN: test -f klee-last/test000003.free.err
+
+int main(int argc, char **argv) {
+ switch(klee_range(0, 3, "range")) {
+ case 0:
+ free(argv);
+ break;
+ case 1:
+ free(argv[0]);
+ break;
+ case 2:
+ free(argv[1]);
+ break;
+ }
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Getenv.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Getenv.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Getenv.c (added)
+++ klee/trunk/test/Runtime/POSIX/Getenv.c Wed May 20 23:36:41 2009
@@ -0,0 +1,21 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --init-env --libc=klee --posix-runtime --exit-on-error %t2.bc --sym-files 1 10
+
+#include <assert.h>
+
+int main(int argc, char **argv) {
+ char *g = getenv("PWD");
+ if (g) {
+ printf("have PWD\n");
+ } else {
+ printf("have no PWD\n");
+ }
+
+ g = getenv("HELLO");
+ if (!g || strcmp(g, "nice")==0) {
+ printf("getenv(\"HELLO\") = %p\n", g);
+ if (g) assert(strcmp(getenv("HELLO"),"nice") == 0);
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Ioctl.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Ioctl.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Ioctl.c (added)
+++ klee/trunk/test/Runtime/POSIX/Ioctl.c Wed May 20 23:36:41 2009
@@ -0,0 +1,31 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --init-env --posix-runtime --exit-on-error %t.bc --sym-files 0 4
+
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <asm/ioctls.h>
+#include <errno.h>
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ struct stat s;
+ struct termios ts;
+
+ assert(fstat(0, &s) == 0);
+
+ assert(ioctl(10, FIONREAD, &ts) == -1 && errno == EBADF);
+
+ if (S_ISCHR(s.st_mode)) {
+ printf("is chr\n");
+ assert(ioctl(0, TIOCGWINSZ, &ts) == 0);
+ } else {
+ printf("not chr\n");
+ // I think TC* ioctls basically always fail on nonchr?
+ assert(ioctl(0, TIOCGWINSZ, &ts) == -1);
+ assert(errno == ENOTTY);
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Isatty.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Isatty.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Isatty.c (added)
+++ klee/trunk/test/Runtime/POSIX/Isatty.c Wed May 20 23:36:41 2009
@@ -0,0 +1,33 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --libc=uclibc --posix-runtime --init-env %t.bc --sym-files 0 10 --sym-stdout 2>%t.log
+
+// RUN: test -f klee-last/test000001.bout
+// RUN: test -f klee-last/test000002.bout
+// RUN: test -f klee-last/test000003.bout
+// RUN: test -f klee-last/test000004.bout
+
+// RUN: grep -q "stdin is a tty" %t.log
+// RUN: grep -q "stdin is NOT a tty" %t.log
+// RUN: grep -q "stdout is a tty" %t.log
+// RUN: grep -q "stdout is NOT a tty" %t.log
+
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+ int fd0 = 0; // stdin
+ int fd1 = 1; // stdout
+
+ int r = isatty(fd0);
+ if (r)
+ fprintf(stderr, "stdin is a tty\n");
+ else fprintf(stderr, "stdin is NOT a tty\n");
+
+ r = isatty(fd1);
+ if (r)
+ fprintf(stderr, "stdout is a tty\n");
+ else fprintf(stderr, "stdout is NOT a tty\n");
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/PrgName.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/PrgName.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/PrgName.c (added)
+++ klee/trunk/test/Runtime/POSIX/PrgName.c Wed May 20 23:36:41 2009
@@ -0,0 +1,31 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t2.bc
+// RUN: %klee --init-env --posix-runtime --exit-on-error %t2.bc --sym-arg 10 >%t.log
+// RUN: test -f klee-last/test000001.bout
+// RUN: test -f klee-last/test000002.bout
+// RUN: grep -q "No" %t.log
+// RUN: grep -qv "Yes" %t.log
+
+
+/* Simple test for argv[0] */
+
+#include <stdio.h>
+
+int f(int argc, char **argv) {
+
+ if (argv[0][5] == '7')
+ printf("Yes\n");
+ else printf("No\n");
+
+ printf("%c\n", argv[0][5]);
+
+ if (argv[1][1] == 4)
+ printf("4\n");
+ printf("not 4\n");
+
+ return 0;
+}
+
+
+int main(int argc, char **argv) {
+ f(argc, argv);
+}
Added: klee/trunk/test/Runtime/POSIX/Read1.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Read1.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Read1.c (added)
+++ klee/trunk/test/Runtime/POSIX/Read1.c Wed May 20 23:36:41 2009
@@ -0,0 +1,34 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --exit-on-error --posix-runtime --init-env %t.bc --sym-files 1 8 >%t.log
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+ char buf[32];
+
+ // If count is zero, read() returns zero and has no other results. (man page)
+ int x = read(0, 0, 0);
+ assert(x == 0);
+
+ int fd = open("A", O_RDONLY);
+ assert(fd != -1);
+
+ // EFAULT buf is outside your accessible address space. (man page)
+ x = read(fd, 0, 1);
+ assert(x == -1 && errno == EFAULT);
+
+ // EBADF fd is not a valid file descriptor (man page)
+ x = read(-1, buf, 1);
+ assert(x == -1 && errno == EBADF);
+
+ fd = open("A", O_RDONLY);
+ assert(fd != -1);
+ x = read(fd, buf, 1);
+ assert(x == 1);
+}
+
Added: klee/trunk/test/Runtime/POSIX/SELinux.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/SELinux.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/SELinux.c (added)
+++ klee/trunk/test/Runtime/POSIX/SELinux.c Wed May 20 23:36:41 2009
@@ -0,0 +1,30 @@
+/* Very basic test, as right now SELinux support is extremely basic */
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --posix-runtime --exit-on-error %t1.bc --sym-arg 2 > %t.log
+// XFAIL: no-selinux
+
+#include <selinux/selinux.h>
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+
+ security_context_t con;
+
+ assert(argc == 2);
+
+ int selinux = is_selinux_enabled();
+ printf("selinux enabled = %d\n", selinux);
+
+ if (setfscreatecon(argv[1]) < 0)
+ printf("Error: set\n");
+ else printf("Success: set\n");
+
+ if (getfscreatecon(&con) < 0)
+ printf("Error: get\n");
+ else printf("Success: get\n");
+
+ printf("create_con = %s\n", con);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/SeedAndFail.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/SeedAndFail.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/SeedAndFail.c (added)
+++ klee/trunk/test/Runtime/POSIX/SeedAndFail.c Wed May 20 23:36:41 2009
@@ -0,0 +1,38 @@
+// RUN: %llvmgcc %s -emit-llvm -g -O0 -c -o %t.bc
+// RUN: rm -rf tmp-123
+// RUN: %klee --libc=klee --output-dir=tmp-123 --posix-runtime --init-env %t.bc --sym-files 1 10 2>%t.log
+// RUN: klee --seed-out-dir=tmp-123 --zero-seed-extension --libc=uclibc --posix-runtime --init-env %t.bc --sym-files 1 10 --max-fail 1
+// RUN: ls klee-last | grep -c assert | grep 4
+
+
+
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+int main(int argc, char** argv) {
+ char buf[32];
+
+ int fd = open("A", O_RDWR | O_CREAT, S_IRWXU);
+ assert(fd != -1);
+ int nbytes = write(fd, "Hello", sizeof("Hello"));
+ assert(nbytes == sizeof("Hello"));
+
+ off_t off = lseek(fd, 0, SEEK_SET);
+ assert(off != (off_t) -1);
+
+ nbytes = read(fd, buf, sizeof("Hello"));
+ assert(nbytes == sizeof("Hello"));
+
+ int r = close(fd);
+ assert(r == 0);
+
+ r = memcmp(buf, "Hello", sizeof("Hello"));
+ assert(r == 0);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Stdin.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Stdin.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Stdin.c (added)
+++ klee/trunk/test/Runtime/POSIX/Stdin.c Wed May 20 23:36:41 2009
@@ -0,0 +1,56 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --init-env --libc=klee --posix-runtime --exit-on-error %t.bc --sym-files 0 4 > %t.log
+// RUN: grep "mode:file" %t.log
+// RUN: grep "mode:dir" %t.log
+// RUN: grep "mode:chr" %t.log
+// RUN: grep "mode:blk" %t.log
+// RUN: grep "mode:fifo" %t.log
+// RUN: grep "mode:lnk" %t.log
+// RUN: grep "read:sym:yes" %t.log
+// RUN: grep "read:sym:no" %t.log
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+int main(int argc, char **argv) {
+ struct stat stats;
+ assert(fstat(0, &stats) == 0);
+
+ if (S_ISREG(stats.st_mode)) {
+ printf("mode:file\n");
+ } else if (S_ISDIR(stats.st_mode)) {
+ printf("mode:dir\n");
+ } else if (S_ISCHR(stats.st_mode)) {
+ printf("mode:chr\n");
+ } else if (S_ISBLK(stats.st_mode)) {
+ printf("mode:blk\n");
+ } else if (S_ISFIFO(stats.st_mode)) {
+ printf("mode:fifo\n");
+ } else if (S_ISLNK(stats.st_mode)) {
+ printf("mode:lnk\n");
+ } else if (S_ISSOCK(stats.st_mode)) {
+ printf("mode:sock\n");
+ } else {
+ printf("unknown mode\n");
+ }
+
+ assert(stats.st_size==4);
+
+ if (S_ISREG(stats.st_mode)) {
+ char buf[10];
+ int n = read(0, buf, 5);
+ assert(n == 4);
+
+ if (strcmp(buf, "HI!")) {
+ printf("read:sym:yes\n");
+ } else {
+ printf("read:sym:no\n");
+ }
+ }
+
+ fflush(stdout);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Write1.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Write1.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Write1.c (added)
+++ klee/trunk/test/Runtime/POSIX/Write1.c Wed May 20 23:36:41 2009
@@ -0,0 +1,23 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --exit-on-error --libc=uclibc --posix-runtime --init-env %t.bc --sym-files 1 10 --sym-stdout 2>%t.log
+
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+ char buf[32];
+
+ FILE* f = fopen("A", "w");
+ if (!f)
+ klee_silent_exit(0);
+ fwrite("Hello", sizeof("Hello"), 1, f);
+ fclose(f);
+
+ f = fopen("A", "r");
+ fread(buf, sizeof("Hello"), 1, f);
+ fclose(f);
+
+ assert(memcmp(buf, "Hello", sizeof("Hello")) == 0);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/Write2.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/Write2.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/Write2.c (added)
+++ klee/trunk/test/Runtime/POSIX/Write2.c Wed May 20 23:36:41 2009
@@ -0,0 +1,21 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t.bc
+// RUN: %klee --exit-on-error --libc=uclibc --posix-runtime --init-env %t.bc --sym-files 1 10 --sym-stdout 2>%t.log
+
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char** argv) {
+ const char* msg = "This will eventually overflow stdout. ";
+ char buf[32];
+ int i;
+
+ FILE* f = stdout;//fopen("A", "w");
+ if (!f)
+ klee_silent_exit(0);
+
+ for (i = 0; i < 300; i++)
+ fwrite(msg, sizeof(msg), 1, f);
+ fclose(f);
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/POSIX/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/POSIX/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/POSIX/dg.exp (added)
+++ klee/trunk/test/Runtime/POSIX/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,5 @@
+load_lib llvm.exp
+
+if { [klee_supports_posix_runtime] } {
+ RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
+}
Added: klee/trunk/test/Runtime/Uclibc/2007-10-08-optimization-calls-wrong-libc-functions.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/Uclibc/2007-10-08-optimization-calls-wrong-libc-functions.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/Uclibc/2007-10-08-optimization-calls-wrong-libc-functions.c (added)
+++ klee/trunk/test/Runtime/Uclibc/2007-10-08-optimization-calls-wrong-libc-functions.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error --optimize --libc=uclibc %t1.bc
+
+#include <string.h>
+#include <assert.h>
+
+int main() {
+ int a;
+
+ klee_make_symbolic(&a, sizeof a);
+
+ memset(&a, 0, sizeof a);
+
+ if (a) {
+ assert(0);
+ }
+
+ return 0;
+}
Added: klee/trunk/test/Runtime/Uclibc/2008-03-04-libc-atexit-uses-dso-handle.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/Uclibc/2008-03-04-libc-atexit-uses-dso-handle.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/Uclibc/2008-03-04-libc-atexit-uses-dso-handle.c (added)
+++ klee/trunk/test/Runtime/Uclibc/2008-03-04-libc-atexit-uses-dso-handle.c Wed May 20 23:36:41 2009
@@ -0,0 +1,12 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error --libc=uclibc %t1.bc
+
+// just make sure atexit works ok
+
+void boo() {
+}
+
+int main() {
+ atexit(boo);
+ return 0;
+}
Added: klee/trunk/test/Runtime/Uclibc/Environ.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/Uclibc/Environ.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/Uclibc/Environ.c (added)
+++ klee/trunk/test/Runtime/Uclibc/Environ.c Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --libc=uclibc --exit-on-error %t1.bc
+
+#include <assert.h>
+
+int main() {
+ printf("HOME: %s\n", getenv("HOME"));
+ assert(getenv("HOME") != 0);
+ return 0;
+}
Added: klee/trunk/test/Runtime/Uclibc/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/Runtime/Uclibc/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/Runtime/Uclibc/dg.exp (added)
+++ klee/trunk/test/Runtime/Uclibc/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,5 @@
+load_lib llvm.exp
+
+if { [klee_supports_uclibc] } {
+ RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
+}
Added: klee/trunk/test/TestRunner.sh
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/TestRunner.sh?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/TestRunner.sh (added)
+++ klee/trunk/test/TestRunner.sh Wed May 20 23:36:41 2009
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# TestRunner.sh - This script is used to run the deja-gnu tests exactly like
+# deja-gnu does, by executing the Tcl script specified in the test case's
+# RUN: lines. This is made possible by a simple make target supported by the
+# test/Makefile. All this script does is invoke that make target.
+#
+# Usage:
+# TestRunner.sh {script_names}
+#
+# This script is typically used by cd'ing to a test directory and then
+# running TestRunner.sh with a list of test file names you want to run.
+#
+TESTPATH=`pwd`
+SUBDIR=""
+if test `dirname $1` = "." ; then
+ while test `basename $TESTPATH` != "test" -a ! -z "$TESTPATH" ; do
+ tmp=`basename $TESTPATH`
+ SUBDIR="$tmp/$SUBDIR"
+ TESTPATH=`dirname $TESTPATH`
+ done
+fi
+
+for TESTFILE in "$@" ; do
+ if test `dirname $TESTFILE` = . ; then
+ if test -d "$TESTPATH" ; then
+ cd $TESTPATH
+ make check-one TESTONE="$SUBDIR$TESTFILE"
+ cd $PWD
+ else
+ echo "Can't find klee/test directory in " `pwd`
+ fi
+ else
+ make check-one TESTONE=$TESTFILE
+ fi
+done
Propchange: klee/trunk/test/TestRunner.sh
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/test/lib/llvm.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/lib/llvm.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/lib/llvm.exp (added)
+++ klee/trunk/test/lib/llvm.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,213 @@
+# This procedure executes one line of a test case's execution script.
+proc execOneLine { test PRS outcome lineno line } {
+ set status 0
+ set resultmsg ""
+ set retval [ catch { eval exec -keepnewline -- $line } errmsg ]
+ if { $retval != 0 } {
+ set code [lindex $::errorCode 0]
+ set lineno [expr $lineno + 1]
+ if { $PRS != ""} {
+ set PRS " for $PRS"
+ }
+ set errmsg " at line $lineno\nwhile running: $line\n$errmsg"
+ switch "$code" {
+ CHILDSTATUS {
+ set status [lindex $::errorCode 2]
+ if { $status != 0 } {
+ set resultmsg "$test$PRS\nFailed with exit($status)$errmsg"
+ }
+ }
+ CHILDKILLED {
+ set signal [lindex $::errorCode 2]
+ set resultmsg "$test$PRS\nFailed with signal($signal)$errmsg"
+ }
+ CHILDSUSP {
+ set signal [lindex $::errorCode 2]
+ set resultmsg "$test$PRS\nFailed with suspend($signal)$errmsg"
+ }
+ POSIX {
+ set posixNum [lindex $::errorCode 1]
+ set posixMsg [lindex $::errorCode 2]
+ set resultmsg "$test$PRS\nFailed with posix($posixNum,$posixMsg)$errmsg"
+ }
+ NONE {
+ }
+ default {
+ }
+ }
+ }
+ return $resultmsg
+}
+
+# This procedure performs variable substitutions on the RUN: lines of a test
+# cases.
+proc substitute { line test tmpFile } {
+ global srcroot objroot srcdir objdir subdir target_triplet prcontext
+ global llvmgcc llvmgxx llvmgcc_version llvmgccmajvers
+ global gccpath gxxpath compile_c compile_cxx link shlibext llvmlibsdir
+ global llvmtoolsdir
+ set path [file join $srcdir $subdir]
+
+ # Substitute all Tcl variables.
+ set new_line [subst $line ]
+
+ #replace %prcontext with prcontext.tcl (Must replace before %p)
+ regsub -all {%prcontext} $new_line $prcontext new_line
+ #replace %llvmgcc with actual path to llvmgcc
+ regsub -all {%llvmgcc} $new_line "$llvmgcc -emit-llvm" new_line
+ #replace %llvmgxx with actual path to llvmg++
+ regsub -all {%llvmgxx} $new_line "$llvmgxx -emit-llvm" new_line
+ #replace %compile_c with C compilation command
+ regsub -all {%compile_c} $new_line "$compile_c" new_line
+ #replace %compile_cxx with C++ compilation command
+ regsub -all {%compile_cxx} $new_line "$compile_cxx" new_line
+ #replace %link with C++ link command
+ regsub -all {%link} $new_line "$link" new_line
+ #replace %shlibext with shared library extension
+ regsub -all {%shlibext} $new_line "$shlibext" new_line
+ #replace %llvmlibsdir with configure library directory
+ regsub -all {%llvmlibsdir} $new_line "$llvmlibsdir" new_line
+ #replace %klee with klee binary
+ regsub -all {%klee} $new_line "klee" new_line
+ #replace %kleaver with kleaver binary
+ regsub -all {%kleaver} $new_line "kleaver" new_line
+ #replace %p with path to source,
+ regsub -all {%p} $new_line [file join $srcdir $subdir] new_line
+ #replace %s with filename
+ regsub -all {%s} $new_line $test new_line
+ #replace %t with temp filenames
+ regsub -all {%t} $new_line $tmpFile new_line
+ #replace %% with %
+ regsub -all {%%} $new_line % new_line
+ return $new_line
+}
+
+# This procedure runs the set of tests for the test_source_files array.
+proc RunLLVMTests { test_source_files } {
+ global srcroot objroot srcdir objdir subdir TEST_FEATURE_LIST target_triplet
+ set timeout 60
+
+ set path [file join $objdir $subdir]
+
+ #Make Output Directory if it does not exist already
+ if { [file exists path] } {
+ cd $path
+ } else {
+ file mkdir $path
+ cd $path
+ }
+
+ file mkdir Output
+ cd Output
+
+ foreach test $test_source_files {
+ #Should figure out best way to set the timeout
+ #set timeout 40
+
+ set filename [file tail $test]
+ set outcome PASS
+ set tmpFile "$filename.tmp"
+
+ #set hasRunline bool to check if testcase has a runline
+ set numLines 0
+
+ # Open the test file and start reading lines
+ set testFileId [ open $test r]
+ set runline ""
+ set PRNUMS ""
+ foreach line [split [read $testFileId] \n] {
+
+ # if its the END. line then stop parsing (optimization for big files)
+ if {[regexp {END.[ *]$} $line match endofscript]} {
+ break
+
+ # if the line is continued, concatenate and continue the loop
+ } elseif {[regexp {RUN: *(.+)(\\)$} $line match oneline suffix]} {
+ set runline "$runline$oneline "
+
+ # if its a terminating RUN: line then do substitution on the whole line
+ # and then save the line.
+ } elseif {[regexp {RUN: *([^&]+)(&&)?} $line match oneline suffix]} {
+ set runline "$runline$oneline"
+ set runline [ substitute $runline $test $tmpFile ]
+ set lines($numLines) $runline
+ set numLines [expr $numLines + 1]
+ set runline ""
+
+ # if its an PR line, save the problem report number
+ } elseif {[regexp {PR([0-9]+)} $line match prnum]} {
+ if {$PRNUMS == ""} {
+ set PRNUMS "PR$prnum"
+ } else {
+ set PRNUMS "$PRNUMS,$prnum"
+ }
+ # if its an XFAIL line, see if we should be XFAILing or not.
+ } elseif {[regexp {XFAIL:[ *](.+)} $line match features]} {
+ set features
+
+ foreach feature [split $features ,] {
+ if { [regexp {\*} $feature match] } {
+ set outcome XFAIL
+ } elseif { [regexp $feature $target_triplet match] } {
+ set outcome XFAIL
+ } elseif { [regexp $feature $TEST_FEATURE_LIST match] } {
+ set outcome XFAIL
+ }
+ }
+ }
+ }
+
+ # Done reading the script
+ close $testFileId
+
+
+ if { $numLines == 0 } {
+ fail "$test: \nDoes not have a RUN line\n"
+ } else {
+ set failed 0
+ for { set i 0 } { $i < $numLines } { set i [ expr $i + 1 ] } {
+ regsub ^.*RUN:(.*) $lines($i) \1 theLine
+ set resultmsg [execOneLine $test $PRNUMS $outcome $i $theLine ]
+ if { $resultmsg != "" } {
+ if { $outcome == "XFAIL" } {
+ xfail "$resultmsg"
+ } else {
+ fail "$resultmsg"
+ }
+ set failed 1
+ break
+ }
+ }
+ if { $failed } {
+ continue
+ } else {
+ if { $PRNUMS != "" } {
+ set PRNUMS " for $PRNUMS"
+ }
+ if { $outcome == "XFAIL" } {
+ xpass "$test$PRNUMS"
+ } else {
+ pass "$test$PRNUMS"
+ }
+ }
+ }
+ }
+}
+
+# Check if klee was configured with POSIX runtime support.
+proc klee_supports_posix_runtime { } {
+ global ENABLE_POSIX_RUNTIME
+ if { $ENABLE_POSIX_RUNTIME == "1" } {
+ return 1
+ }
+ return 0
+}
+
+# Check if klee was configured with uclibc support.
+proc klee_supports_uclibc { } {
+ global ENABLE_UCLIBC
+ if { $ENABLE_UCLIBC == "1" } {
+ return 1
+ }
+ return 0
+}
Added: klee/trunk/test/regression/2007-07-25-invalid-stp-array-binding-to-objectstate.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-07-25-invalid-stp-array-binding-to-objectstate.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-07-25-invalid-stp-array-binding-to-objectstate.c (added)
+++ klee/trunk/test/regression/2007-07-25-invalid-stp-array-binding-to-objectstate.c Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <assert.h>
+
+int main(void) {
+ char c[2];
+
+ klee_make_symbolic(&c, sizeof(c));
+
+ if (c[0] > 10) {
+ int x;
+
+ c[1] = 1; // copy object state
+
+ assert(c[0] > 10);
+ }
+
+ return 0;
+}
Added: klee/trunk/test/regression/2007-07-30-unflushed-byte.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-07-30-unflushed-byte.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-07-30-unflushed-byte.c (added)
+++ klee/trunk/test/regression/2007-07-30-unflushed-byte.c Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <assert.h>
+
+int main() {
+ char i, x[3];
+
+ klee_make_symbolic(&i, sizeof i);
+
+ x[0] = i;
+
+ // DEMAND FAILED:Memory.cpp:read8:199: <isByteFlushed(offset)> is false: "unflushed byte without cache value"
+ char y = x[1];
+
+ return 0;
+}
+
Added: klee/trunk/test/regression/2007-08-01-bool-zext-in-call.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-01-bool-zext-in-call.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-01-bool-zext-in-call.ll (added)
+++ klee/trunk/test/regression/2007-08-01-bool-zext-in-call.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+; RUN: llvm-as -f %s -o - | %klee 2> %t1.log
+; RUN: not test -f klee-last/test0001.abort.err
+
+declare void @klee_abort()
+
+define i32 @foo(i8 signext %val) {
+ %tmp = zext i8 %val to i32
+ ret i32 %tmp
+}
+
+define i32 @main() {
+ %res = call i32 bitcast (i32 (i8 signext)* @foo to i32 (i1)*)( i1 1 )
+ %check = icmp ne i32 %res, 255
+ br i1 %check, label %error, label %exit
+
+error:
+ call void @klee_abort()
+ unreachable
+
+exit:
+ ret i32 0
+}
Added: klee/trunk/test/regression/2007-08-01-cache-unclear-on-overwrite-flushed.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-01-cache-unclear-on-overwrite-flushed.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-01-cache-unclear-on-overwrite-flushed.c (added)
+++ klee/trunk/test/regression/2007-08-01-cache-unclear-on-overwrite-flushed.c Wed May 20 23:36:41 2009
@@ -0,0 +1,25 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <assert.h>
+#include <stdio.h>
+
+int main() {
+ unsigned char x;
+
+ klee_make_symbolic(&x, sizeof x);
+ if (x >= 2) klee_silent_exit(0);
+
+ char delete[2] = {0,1};
+
+ char tmp = delete[ x ];
+ char tmp2 = delete[0];
+ delete[ x ] = tmp2;
+
+ if (x==1) {
+ assert(delete[1] == 0);
+ return 0;
+ }
+
+ return 0;
+}
Added: klee/trunk/test/regression/2007-08-06-64bit-shift.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-06-64bit-shift.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-06-64bit-shift.c (added)
+++ klee/trunk/test/regression/2007-08-06-64bit-shift.c Wed May 20 23:36:41 2009
@@ -0,0 +1,20 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <assert.h>
+
+int main() {
+ int d;
+
+ klee_make_symbolic( &d, sizeof(d) );
+
+ int l = d - 1;
+ unsigned long long m = ((unsigned long long) l << 32) / d;
+ if (d==2) {
+ assert(m == 2147483648u);
+ }
+
+ klee_silent_exit(0);
+
+ return 0;
+}
Added: klee/trunk/test/regression/2007-08-06-access-after-free.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-06-access-after-free.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-06-access-after-free.c (added)
+++ klee/trunk/test/regression/2007-08-06-access-after-free.c Wed May 20 23:36:41 2009
@@ -0,0 +1,29 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+#include <assert.h>
+
+int main() {
+ int a;
+ unsigned char *p = malloc(4);
+
+ klee_make_symbolic(&a, sizeof a);
+ klee_make_symbolic(p, sizeof p);
+
+ p[0] |= 16;
+
+ if (a) {
+ free(p);
+
+ // this should give an error instead of
+ // pulling the state from the parent, where
+ // it is not free
+ assert(p[0] > 10);
+
+ return 0;
+ }
+
+ assert(p[0] > 10);
+
+ return 0;
+}
Added: klee/trunk/test/regression/2007-08-08-free-zero.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-08-free-zero.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-08-free-zero.c (added)
+++ klee/trunk/test/regression/2007-08-08-free-zero.c Wed May 20 23:36:41 2009
@@ -0,0 +1,8 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: ls klee-last | not grep *.err
+
+int main() {
+ free(0);
+ return 0;
+}
Added: klee/trunk/test/regression/2007-08-16-invalid-constant-value.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-16-invalid-constant-value.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-16-invalid-constant-value.c (added)
+++ klee/trunk/test/regression/2007-08-16-invalid-constant-value.c Wed May 20 23:36:41 2009
@@ -0,0 +1,31 @@
+// RUN: rm -f %t4.out %t4.err %t4.log
+// RUN: %llvmgcc %s -emit-llvm -O2 -c -o %t1.bc
+// RUN: llvm-as -f ../../Feature/_utils._ll -o %t2.bc
+// RUN: llvm-ld -disable-opt %t1.bc %t2.bc -o %t3
+// RUN: %klee %t3.bc
+
+#include <assert.h>
+
+#include "../Feature/utils.h"
+
+int main() {
+ unsigned char a;
+
+ klee_make_symbolic(&a, sizeof a);
+
+ // demand was firing here because an invalid constant
+ // value was being created when implied value did not
+ // subtract using the proper type (so overflowed into
+ // invalid bits)
+ if (util_make_concat2(a+0xCD,0xCD) == 0xABCD) {
+ assert(!klee_is_symbolic(a));
+ printf("add constant case: %d\n", a);
+ }
+
+ if (util_make_concat2(0x0B-a,0xCD) == 0xABCD) {
+ assert(!klee_is_symbolic(a));
+ printf("sub constant case: %d\n", a);
+ }
+
+ return 0;
+}
Added: klee/trunk/test/regression/2007-08-16-valid-write-to-freed-object.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-08-16-valid-write-to-freed-object.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-08-16-valid-write-to-freed-object.c (added)
+++ klee/trunk/test/regression/2007-08-16-valid-write-to-freed-object.c Wed May 20 23:36:41 2009
@@ -0,0 +1,24 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+
+unsigned sym() {
+ unsigned x;
+ klee_make_symbolic(&x, sizeof x);
+ return x;
+}
+
+int main() {
+ unsigned x, y;
+
+ // sym returns a symbolic object, but because it is
+ // alloca'd it is freed on sym()s return. thats fine,
+ // but the problem is that IVC is going to try to write
+ // into the object right here.
+ //
+ // to support this we need to have a facility for making
+ // state local copies of a freed object.
+ if (sym() == 0)
+ printf("ok\n");
+
+ return 0;
+}
Added: klee/trunk/test/regression/2007-10-11-free-of-alloca.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-10-11-free-of-alloca.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-10-11-free-of-alloca.c (added)
+++ klee/trunk/test/regression/2007-10-11-free-of-alloca.c Wed May 20 23:36:41 2009
@@ -0,0 +1,9 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.free.err
+
+int main() {
+ int buf[4];
+ free(buf); // this should give runtime error, not crash
+ return 0;
+}
Added: klee/trunk/test/regression/2007-10-11-illegal-access-after-free-and-branch.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-10-11-illegal-access-after-free-and-branch.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-10-11-illegal-access-after-free-and-branch.c (added)
+++ klee/trunk/test/regression/2007-10-11-illegal-access-after-free-and-branch.c Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+// RUN: %llvmgcc %s -emit-llvm -g -c -o %t1.bc
+// RUN: %klee --optimize %t1.bc
+// RUN: test -f klee-last/test000001.ptr.err
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+int main(int argc, char **argv) {
+ unsigned char *buf = malloc(3);
+ klee_make_symbolic(buf, 3);
+ if (buf[0]>4) klee_silent_exit(0);
+ unsigned char x = buf[1];
+ free(buf);
+ if (x)
+ return buf[2];
+ klee_silent_exit(0);
+ return 0;
+}
Added: klee/trunk/test/regression/2007-10-12-failed-make-symbolic-after-copy.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2007-10-12-failed-make-symbolic-after-copy.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2007-10-12-failed-make-symbolic-after-copy.c (added)
+++ klee/trunk/test/regression/2007-10-12-failed-make-symbolic-after-copy.c Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.bout
+
+int main() {
+ unsigned x, y[4];
+
+ klee_make_symbolic(&x,sizeof x);
+ if (x>=4) klee_silent_exit(0);
+
+ y[x] = 0;
+
+ if (x) { // force branch so y is copied
+ klee_make_symbolic(&y, sizeof y);
+ if (y[x]==0) klee_silent_exit(0);
+ return 0; // should be reachable
+ } else {
+ // force read here in case we try to optimize copies smartly later
+ if (y[x]==0) klee_silent_exit(0);
+ return 0; // not reachable
+ }
+}
Added: klee/trunk/test/regression/2008-02-11-phi-nodes-after-invoke.ll
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2008-02-11-phi-nodes-after-invoke.ll?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2008-02-11-phi-nodes-after-invoke.ll (added)
+++ klee/trunk/test/regression/2008-02-11-phi-nodes-after-invoke.ll Wed May 20 23:36:41 2009
@@ -0,0 +1,47 @@
+; RUN: llvm-as -f %s -o - | %klee --no-output --exit-on-error
+
+declare void @klee_abort()
+
+define i32 @foo(i32 %val, i32 %fail) {
+ %code = icmp ne i32 0, %fail
+ br i1 %code, label %failing, label %return
+failing:
+ unwind
+return:
+ ret i32 %val
+}
+
+define void @test(i32 %should_fail) {
+entry:
+ %res0 = invoke i32 (i32, i32)* @foo(i32 0, i32 %should_fail)
+ to label %check_phi unwind label %error
+
+error:
+ %res1 = zext i8 1 to i32
+ br label %check_phi
+
+check_phi:
+ %val = phi i32 [%never_used, %never_used_label], [%res0, %entry], [%res1, %error]
+ %ok = icmp eq i32 %val, %should_fail
+ br i1 %ok, label %exit, label %on_error
+ call void @klee_abort()
+ unreachable
+
+on_error:
+ call void @klee_abort()
+ unreachable
+
+exit:
+ ret void
+
+ ;; this is so we hopefully fail if incomingBBIndex isn't set properly
+never_used_label:
+ %never_used = zext i8 undef to i32
+ br label %check_phi
+}
+
+define i32 @main() {
+ call void (i32)* @test(i32 0)
+ call void (i32)* @test(i32 1)
+ ret i32 0
+}
Added: klee/trunk/test/regression/2008-03-04-free-of-global.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2008-03-04-free-of-global.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2008-03-04-free-of-global.c (added)
+++ klee/trunk/test/regression/2008-03-04-free-of-global.c Wed May 20 23:36:41 2009
@@ -0,0 +1,10 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee %t1.bc
+// RUN: test -f klee-last/test000001.free.err
+
+int buf[4];
+
+int main() {
+ free(buf); // this should give runtime error, not crash
+ return 0;
+}
Added: klee/trunk/test/regression/2008-03-11-free-of-malloc-zero.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2008-03-11-free-of-malloc-zero.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2008-03-11-free-of-malloc-zero.c (added)
+++ klee/trunk/test/regression/2008-03-11-free-of-malloc-zero.c Wed May 20 23:36:41 2009
@@ -0,0 +1,16 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+#include <stdlib.h>
+
+int main() {
+ // concrete case
+ void *p = malloc(0);
+ free(p);
+
+ p = malloc(0);
+ void *arr[4] = { p, 0, 0, 0 };
+
+ // symbolic case
+ free(arr[klee_range(0, 4, "range")]);
+}
Added: klee/trunk/test/regression/2008-04-10-bad-alloca-free.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2008-04-10-bad-alloca-free.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2008-04-10-bad-alloca-free.c (added)
+++ klee/trunk/test/regression/2008-04-10-bad-alloca-free.c Wed May 20 23:36:41 2009
@@ -0,0 +1,12 @@
+// RUN: %llvmgcc %s -emit-llvm -O0 -c -o %t1.bc
+// RUN: %klee --exit-on-error %t1.bc
+
+void f(int *addr) {
+ klee_make_symbolic_name(addr, sizeof *addr, "moo");
+}
+
+int main() {
+ int x;
+ f(&x);
+ return x;
+}
Added: klee/trunk/test/regression/2008-05-23-gep-with-global-const.c
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/2008-05-23-gep-with-global-const.c?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/2008-05-23-gep-with-global-const.c (added)
+++ klee/trunk/test/regression/2008-05-23-gep-with-global-const.c Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+// RUN: %llvmgcc -O0 -c -o %t.bc %s
+// RUN: %klee --exit-on-error %t.bc
+
+#include <assert.h>
+
+int a;
+
+int main() {
+ void *p1 = &((char*) 0)[(long) &a];
+ void *p2 = &a;
+
+ assert(p1 == p2);
+
+ return 0;
+}
Added: klee/trunk/test/regression/dg.exp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/test/regression/dg.exp?rev=72205&view=auto
==============================================================================
--- klee/trunk/test/regression/dg.exp (added)
+++ klee/trunk/test/regression/dg.exp Wed May 20 23:36:41 2009
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,llx,c,cpp,tr}]]
Added: klee/trunk/tools/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/Makefile (added)
+++ klee/trunk/tools/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,21 @@
+#===-- tools/Makefile --------------------------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+#
+# Relative path to the top of the source tree.
+#
+LEVEL=..
+
+#
+# List all of the subdirectories that we will compile.
+#
+PARALLEL_DIRS=klee kleaver klee-bout-tool gen-random-bout
+# FIXME: Move qplayer functionality into kleaver
+
+include $(LEVEL)/Makefile.common
Added: klee/trunk/tools/gen-random-bout/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/gen-random-bout/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/gen-random-bout/Makefile (added)
+++ klee/trunk/tools/gen-random-bout/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,7 @@
+##===- tools/klee/Makefile ---------------*- Makefile -*-===##
+
+LEVEL=../..
+TOOLNAME = gen-random-bout
+USEDLIBS = kleeBasic.a
+
+include $(LEVEL)/Makefile.common
Added: klee/trunk/tools/gen-random-bout/gen-random-bout.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/gen-random-bout/gen-random-bout.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/gen-random-bout/gen-random-bout.cpp (added)
+++ klee/trunk/tools/gen-random-bout/gen-random-bout.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,124 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "klee/Internal/ADT/BOut.h"
+
+// --sym-args 0 1 10 --sym-args 0 2 2 --sym-files 1 8 --sym-stdout
+static int getint(char *i) {
+ if(!i) {
+ fprintf(stderr, "ran out of arguments!\n");
+ assert(i);
+ }
+ return atoi(i);
+}
+
+#define MAX 64
+static void push_obj(BOut *b, const char *name, unsigned non_zero_bytes,
+ unsigned total_bytes) {
+ BOutObject *o = &b->objects[b->numObjects++];
+ assert(b->numObjects < MAX);
+
+ o->name = strdup(name);
+ o->numBytes = total_bytes;
+ o->bytes = (unsigned char *)malloc(o->numBytes);
+
+ unsigned i;
+ for(i = 0; i < non_zero_bytes; i++)
+ o->bytes[i] = random();
+
+ for(i = non_zero_bytes; i < total_bytes; i++)
+ o->bytes[i] = 0;
+}
+
+
+static void push_range(BOut *b, const char *name, unsigned value) {
+ BOutObject *o = &b->objects[b->numObjects++];
+ assert(b->numObjects < MAX);
+
+ o->name = strdup(name);
+ o->numBytes = 4;
+ o->bytes = (unsigned char *)malloc(o->numBytes);
+
+ *(unsigned*)o->bytes = value;
+}
+
+int main(int argc, char *argv[]) {
+ unsigned i, narg;
+ unsigned sym_stdout = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <random-seed> <argument-types>\n", argv[0]);
+ fprintf(stderr, " If <random-seed> is 0, time(NULL)*getpid() is used as a seed\n");
+ fprintf(stderr, " <argument-types> are the ones accepted by KLEE: --sym-args, --sym-files etc.\n");
+ fprintf(stderr, " Ex: %s 100 --sym-args 0 2 2 --sym-files 1 8\n", argv[0]);
+ exit(1);
+ }
+
+ unsigned seed = atoi(argv[1]);
+ if (seed)
+ srandom(seed);
+ else srandom(time(NULL) * getpid());
+
+ BOut b;
+ b.numArgs = argc;
+ b.args = argv;
+ b.symArgvs = 0;
+ b.symArgvLen = 0;
+
+ b.numObjects = 0;
+ b.objects = (BOutObject *)malloc(MAX * sizeof *b.objects);
+
+ for(i = 2; i < (unsigned)argc; i++) {
+ if(strcmp(argv[i], "--sym-args") == 0) {
+ unsigned lb = getint(argv[++i]);
+ unsigned ub = getint(argv[++i]);
+ unsigned nbytes = getint(argv[++i]);
+
+ narg = random() % (ub - lb) + lb;
+ push_range(&b, "range", narg);
+
+ while(narg-- > 0) {
+ unsigned x = random() % (nbytes + 1);
+
+ // A little different than how klee does it but more natural
+ // for random.
+ static int total_args;
+ char arg[1024];
+
+ sprintf(arg, "arg%d", total_args++);
+ push_obj(&b, arg, x, nbytes+1);
+ }
+ } else if(strcmp(argv[i], "--sym-stdout") == 0) {
+ if(!sym_stdout) {
+ sym_stdout = 1;
+ push_obj(&b, "stdout", 1024, 1024);
+ push_obj(&b, "stdout-stat", sizeof(struct stat64),
+ sizeof(struct stat64));
+ }
+ } else if(strcmp(argv[i], "--sym-files") == 0) {
+ unsigned nfiles = getint(argv[++i]);
+ unsigned nbytes = getint(argv[++i]);
+
+ while(nfiles-- > 0) {
+ push_obj(&b, "file", nbytes, nbytes);
+ push_obj(&b, "file-stat", sizeof(struct stat64), sizeof(struct stat64));
+ }
+
+ push_obj(&b, "stdin", nbytes, nbytes);
+ push_obj(&b, "stdin-stat", sizeof(struct stat64), sizeof(struct stat64));
+ } else {
+ fprintf(stderr, "unexpected option <%s>\n", argv[i]);
+ assert(0);
+ }
+ }
+
+ if (!bOut_toFile(&b, "file.bout"))
+ assert(0);
+ return 0;
+}
Added: klee/trunk/tools/kleaver/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/kleaver/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/kleaver/Makefile (added)
+++ klee/trunk/tools/kleaver/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,19 @@
+#===-- tools/kleaver/Makefile ------------------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+LEVEL=../..
+TOOLNAME = kleaver
+# FIXME: Ideally we wouldn't have any LLVM dependencies here, which
+# means kicking out klee's Support.
+USEDLIBS = kleaverExpr.a kleaverSolver.a kleeSupport.a kleeBasic.a
+LINK_COMPONENTS = support
+
+include $(LEVEL)/Makefile.common
+
+LIBS += -lstp
Added: klee/trunk/tools/kleaver/main.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/kleaver/main.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/kleaver/main.cpp (added)
+++ klee/trunk/tools/kleaver/main.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,120 @@
+#include "expr/Lexer.h"
+#include "expr/Parser.h"
+
+#include "klee/Expr.h"
+#include "klee/Solver.h"
+#include "klee/util/ExprPPrinter.h"
+#include "klee/util/ExprVisitor.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Streams.h"
+#include "llvm/System/Signals.h"
+
+#include <iomanip>
+#include <sstream>
+
+using namespace llvm;
+using namespace klee;
+using namespace klee::expr;
+
+namespace {
+ llvm::cl::opt<std::string>
+ InputFile(llvm::cl::desc("<input query log>"), llvm::cl::Positional,
+ llvm::cl::init("-"));
+
+ enum ToolActions {
+ PrintTokens,
+ PrintAST
+ };
+
+ static llvm::cl::opt<ToolActions>
+ ToolAction(llvm::cl::desc("Tool actions:"),
+ llvm::cl::init(PrintTokens),
+ llvm::cl::values(
+ clEnumValN(PrintTokens, "print-tokens",
+ "Print tokens from the input file."),
+ clEnumValN(PrintAST, "print-ast",
+ "Print parsed AST nodes from the input file."),
+ clEnumValEnd));
+}
+
+static std::string escapedString(const char *start, unsigned length) {
+ std::stringstream s;
+ for (unsigned i=0; i<length; ++i) {
+ char c = start[i];
+ if (isprint(c)) {
+ s << c;
+ } else if (c == '\n') {
+ s << "\\n";
+ } else {
+ s << "\\x" << hexdigit(((unsigned char) c >> 4) & 0xF) << hexdigit((unsigned char) c & 0xF);
+ }
+ }
+ return s.str();
+}
+
+static void PrintInputTokens(const MemoryBuffer *MB) {
+ Lexer L(MB);
+ Token T;
+ do {
+ L.Lex(T);
+ llvm::cout << "(Token \"" << T.getKindName() << "\" "
+ << "\"" << escapedString(T.start, T.length) << "\" "
+ << T.length << " "
+ << T.line << " " << T.column << ")\n";
+ } while (T.kind != Token::EndOfFile);
+}
+
+static bool PrintInputAST(const char *Filename,
+ const MemoryBuffer *MB) {
+ Parser *P = Parser::Create(Filename, MB);
+ P->SetMaxErrors(20);
+ while (Decl *D = P->ParseTopLevelDecl()) {
+ if (!P->GetNumErrors())
+ D->dump();
+ delete D;
+ }
+
+ bool success = true;
+ if (unsigned N = P->GetNumErrors()) {
+ llvm::cerr << Filename << ": parse failure: "
+ << N << " errors.\n";
+ success = false;
+ }
+ delete P;
+
+ return success;
+}
+
+int main(int argc, char **argv) {
+ bool success = true;
+
+ llvm::sys::PrintStackTraceOnErrorSignal();
+ llvm::cl::ParseCommandLineOptions(argc, argv);
+
+ std::string ErrorStr;
+ MemoryBuffer *MB = MemoryBuffer::getFileOrSTDIN(InputFile.c_str(), &ErrorStr);
+ if (!MB) {
+ llvm::cerr << argv[0] << ": ERROR: " << ErrorStr << "\n";
+ return 1;
+ }
+
+ switch (ToolAction) {
+ case PrintTokens:
+ PrintInputTokens(MB);
+ break;
+ case PrintAST:
+ success = PrintInputAST(InputFile=="-" ? "<stdin>" : InputFile.c_str(), MB);
+ break;
+ default:
+ llvm::cerr << argv[0] << ": ERROR: Unknown program action!\n";
+ }
+
+ delete MB;
+
+ llvm::llvm_shutdown();
+ return success ? 0 : 1;
+}
Added: klee/trunk/tools/klee-bout-tool/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/klee-bout-tool/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/klee-bout-tool/Makefile (added)
+++ klee/trunk/tools/klee-bout-tool/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,46 @@
+#===-- tools/klee-bout-tool/Makefile -----------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+LEVEL = ../..
+
+TOOLSCRIPTNAME := klee-bout-tool
+
+include $(LEVEL)/Makefile.common
+
+# FIXME: Move this stuff (to "build" a script) into Makefile.rules.
+
+ToolBuildPath := $(ToolDir)/$(TOOLSCRIPTNAME)
+
+all-local:: $(ToolBuildPath)
+
+$(ToolBuildPath): $(ToolDir)/.dir
+
+$(ToolBuildPath): $(TOOLSCRIPTNAME)
+ $(Echo) Copying $(BuildMode) script $(TOOLSCRIPTNAME)
+ $(Verb) $(CP) -f $(TOOLSCRIPTNAME) "$@"
+ $(Verb) chmod 0755 "$@"
+
+ifdef NO_INSTALL
+install-local::
+ $(Echo) Install circumvented with NO_INSTALL
+uninstall-local::
+ $(Echo) Uninstall circumvented with NO_INSTALL
+else
+DestTool = $(PROJ_bindir)/$(TOOLSCRIPTNAME)
+
+install-local:: $(DestTool)
+
+$(DestTool): $(ToolBuildPath) $(PROJ_bindir)
+ $(Echo) Installing $(BuildMode) $(DestTool)
+ $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool)
+
+uninstall-local::
+ $(Echo) Uninstalling $(BuildMode) $(DestTool)
+ -$(Verb) $(RM) -f $(DestTool)
+endif
Added: klee/trunk/tools/klee-bout-tool/klee-bout-tool
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/klee-bout-tool/klee-bout-tool?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/klee-bout-tool/klee-bout-tool (added)
+++ klee/trunk/tools/klee-bout-tool/klee-bout-tool Wed May 20 23:36:41 2009
@@ -0,0 +1,106 @@
+#!/usr/bin/python
+
+import os
+import struct
+import sys
+
+version_no=2
+
+class BOutError(Exception):
+ pass
+
+class BOut:
+ @staticmethod
+ def fromfile(path):
+ if not os.path.exists(path):
+ print "ERROR: file %s not found" % (path)
+ sys.exit(1)
+
+ f = open(path,'rb')
+ hdr = f.read(5)
+ if len(hdr)!=5 or hdr!='BOUT\n':
+ raise BOutError,'unrecognized file'
+ version, = struct.unpack('>i', f.read(4))
+ if version > version_no:
+ raise BOutError,'unrecognized version'
+ numArgs, = struct.unpack('>i', f.read(4))
+ args = []
+ for i in range(numArgs):
+ size, = struct.unpack('>i', f.read(4))
+ args.append(f.read(size))
+
+ if version >= 2:
+ symArgvs, = struct.unpack('>i', f.read(4))
+ symArgvLen, = struct.unpack('>i', f.read(4))
+ else:
+ symArgvs = 0
+ symArgvLen = 0
+
+ numObjects, = struct.unpack('>i', f.read(4))
+ objects = []
+ for i in range(numObjects):
+ size, = struct.unpack('>i', f.read(4))
+ name = f.read(size)
+ size, = struct.unpack('>i', f.read(4))
+ bytes = f.read(size)
+ objects.append( (name,bytes) )
+
+ # Create an instance
+ b = BOut(version, args, symArgvs, symArgvLen, objects)
+ # Augment with extra filename field
+ b.filename = path
+ return b
+
+ def __init__(self, version, args, symArgvs, symArgvLen, objects):
+ self.version = version
+ self.symArgvs = symArgvs
+ self.symArgvLen = symArgvLen
+ self.args = args
+ self.objects = objects
+
+ # add a field that represents the name of the program used to
+ # generate this .bout file:
+ program_full_path = self.args[0]
+ program_name = os.path.basename(program_full_path)
+ # sometimes program names end in .bc, so strip them
+ if program_name.endswith('.bc'):
+ program_name = program_name[:-3]
+ self.programName = program_name
+
+def trimZeros(str):
+ for i in range(len(str))[::-1]:
+ if str[i] != '\x00':
+ return str[:i+1]
+ return ''
+
+def main(args):
+ from optparse import OptionParser
+ op = OptionParser("usage: %prog [options] files")
+ op.add_option('','--trim-zeros', dest='trimZeros', action='store_true',
+ default=False,
+ help='trim trailing zeros')
+
+ opts,args = op.parse_args()
+ if not args:
+ op.error("incorrect number of arguments")
+
+ for file in args:
+ b = BOut.fromfile(file)
+ pos = 0
+ print 'bout file : %r' % file
+ print 'args : %r' % b.args
+ print 'num objects: %r' % len(b.objects)
+ for i,(name,data) in enumerate(b.objects):
+ if opts.trimZeros:
+ str = trimZeros(data)
+ else:
+ str = data
+
+ print 'object %4d: name: %r' % (i, name)
+ print 'object %4d: size: %r' % (i, len(data))
+ print 'object %4d: data: %r' % (i, str)
+ if file != args[-1]:
+ print
+
+if __name__=='__main__':
+ main(sys.argv)
Propchange: klee/trunk/tools/klee-bout-tool/klee-bout-tool
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/tools/klee/Debug.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/klee/Debug.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/klee/Debug.cpp (added)
+++ klee/trunk/tools/klee/Debug.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,12 @@
+#include <klee/Expr.h>
+#include <iostream>
+
+void kdb_printExpr(klee::Expr *e) {
+ llvm::cerr << "expr: " << e << " -- ";
+ if (e) {
+ llvm::cerr << *e;
+ } else {
+ llvm::cerr << "(null)";
+ }
+ llvm::cerr << "\n";
+}
Added: klee/trunk/tools/klee/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/klee/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/klee/Makefile (added)
+++ klee/trunk/tools/klee/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,22 @@
+#===-- tools/klee/Makefile ---------------------------------*- Makefile -*--===#
+#
+# The KLEE Symbolic Virtual Machine
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+LEVEL=../..
+TOOLNAME = klee
+USEDLIBS = kleeCore.a kleeModule.a kleaverSolver.a kleaverExpr.a kleeSupport.a kleeBasic.a
+LINK_COMPONENTS = bitreader bitwriter ipo linker engine
+
+include $(LEVEL)/Makefile.common
+
+ifeq ($(ENABLE_STPLOG), 1)
+ LIBS += -lstplog
+endif
+
+LIBS += -lstp
+#-ltcmalloc
Added: klee/trunk/tools/klee/main.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/tools/klee/main.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/tools/klee/main.cpp (added)
+++ klee/trunk/tools/klee/main.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,1422 @@
+/* -*- mode: c++; c-basic-offset: 2; -*- */
+
+// FIXME: This does not belong here.
+#include "../lib/Core/Common.h"
+
+#include "klee/ExecutionState.h"
+#include "klee/Expr.h"
+#include "klee/Interpreter.h"
+#include "klee/Statistics.h"
+#include "klee/Config/config.h"
+#include "klee/Internal/ADT/BOut.h"
+#include "klee/Internal/ADT/TreeStream.h"
+#include "klee/Internal/Support/ModuleUtil.h"
+#include "klee/Internal/System/Time.h"
+
+#include "llvm/Constants.h"
+#include "llvm/Module.h"
+#include "llvm/ModuleProvider.h"
+#include "llvm/Type.h"
+#include "llvm/InstrTypes.h"
+#include "llvm/Instruction.h"
+#include "llvm/Instructions.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Signals.h"
+#include <iostream>
+#include <fstream>
+#include <cerrno>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <iostream>
+#include <iterator>
+#include <fstream>
+#include <sstream>
+
+using namespace llvm;
+using namespace klee;
+
+namespace {
+ cl::opt<std::string>
+ InputFile(cl::desc("<input bytecode>"), cl::Positional, cl::init("-"));
+
+ cl::opt<std::string>
+ RunInDir("run-in", cl::desc("Change to the given directory prior to executing"));
+
+ cl::opt<std::string>
+ Environ("environ", cl::desc("Parse environ from given file (in \"env\" format)"));
+
+ cl::list<std::string>
+ InputArgv(cl::ConsumeAfter,
+ cl::desc("<program arguments>..."));
+
+ cl::opt<bool>
+ NoOutput("no-output",
+ cl::desc("Don't generate test files"));
+
+ cl::opt<bool>
+ WarnAllExternals("warn-all-externals",
+ cl::desc("Give initial warning for all externals."));
+
+ cl::opt<bool>
+ WriteCVCs("write-cvcs",
+ cl::desc("Write .cvc files for each test case"));
+
+ cl::opt<bool>
+ WritePCs("write-pcs",
+ cl::desc("Write .pc files for each test case"));
+
+ cl::opt<bool>
+ WriteCov("write-cov",
+ cl::desc("Write coverage information for each test case"));
+
+ cl::opt<bool>
+ WriteTestInfo("write-test-info",
+ cl::desc("Write additional test case information"));
+
+ cl::opt<bool>
+ WritePaths("write-paths",
+ cl::desc("Write .path files for each test case"));
+
+ cl::opt<bool>
+ WriteSymPaths("write-sym-paths",
+ cl::desc("Write .sym.path files for each test case"));
+
+ cl::opt<bool>
+ ExitOnError("exit-on-error",
+ cl::desc("Exit if errors occur"));
+
+
+ enum LibcType {
+ NoLibc, KleeLibc, UcLibc
+ };
+
+ cl::opt<LibcType>
+ Libc("libc",
+ cl::desc("Choose libc version (none by default)."),
+ cl::values(clEnumValN(NoLibc, "none", "Don't link in a libc"),
+ clEnumValN(KleeLibc, "klee", "Link in klee libc"),
+ clEnumValN(UcLibc, "uclibc", "Link in uclibc (adapted for klee)"),
+ clEnumValEnd),
+ cl::init(NoLibc));
+
+
+ cl::opt<bool>
+ WithPOSIXRuntime("posix-runtime",
+ cl::desc("Link with POSIX runtime"),
+ cl::init(false));
+
+ cl::opt<bool>
+ OptimizeModule("optimize",
+ cl::desc("Optimize before execution"));
+
+ cl::opt<bool>
+ CheckDivZero("check-div-zero",
+ cl::desc("Inject checks for division-by-zero"),
+ cl::init(true));
+
+ cl::opt<std::string>
+ OutputDir("output-dir",
+ cl::desc("Directory to write results in (defaults to klee-out-N)"),
+ cl::init(""));
+
+ // this is a fake entry, its automagically handled
+ cl::list<std::string>
+ ReadArgsFilesFake("read-args",
+ cl::desc("File to read arguments from (one arg per line)"));
+
+ cl::opt<bool>
+ ReplayKeepSymbolic("replay-keep-symbolic",
+ cl::desc("Replay the test cases only by asserting"
+ "the bytes, not necessarily making them concrete."));
+
+ cl::list<std::string>
+ ReplayOutFile("replay-out",
+ cl::desc("Specify an out file to replay"),
+ cl::value_desc("out file"));
+
+ cl::list<std::string>
+ ReplayOutDir("replay-out-dir",
+ cl::desc("Specify a directory to replay .out files from"),
+ cl::value_desc("output directory"));
+
+ cl::opt<std::string>
+ ReplayPathFile("replay-path",
+ cl::desc("Specify a path file to replay"),
+ cl::value_desc("path file"));
+
+ cl::list<std::string>
+ SeedOutFile("seed-out");
+
+ cl::list<std::string>
+ SeedOutDir("seed-out-dir");
+
+ cl::opt<unsigned>
+ MakeConcreteSymbolic("make-concrete-symbolic",
+ cl::desc("Rate at which to make concrete reads symbolic (0=off)"),
+ cl::init(0));
+
+ cl::opt<bool>
+ InitEnv("init-env",
+ cl::desc("Create custom environment. Options that can be passed as arguments to the programs are: --sym-argv <max-len> --sym-argvs <min-argvs> <max-argvs> <max-len> + file model options"));
+
+ cl::opt<unsigned>
+ StopAfterNTests("stop-after-n-tests",
+ cl::desc("Stop execution after generating the given number of tests. Extra tests corresponding to partially explored paths will also be dumped."),
+ cl::init(0));
+
+ cl::opt<bool>
+ Watchdog("watchdog",
+ cl::desc("Use a watchdog process to enforce --max-time."),
+ cl::init(0));
+}
+
+extern bool WriteTraces;
+extern cl::opt<double> MaxTime;
+
+/***/
+
+class KleeHandler : public InterpreterHandler {
+private:
+ Interpreter *m_interpreter;
+ TreeStreamWriter *m_pathWriter, *m_symPathWriter;
+ std::ostream *m_infoFile;
+
+ char m_outputDirectory[1024];
+ unsigned m_testIndex; // number of tests written so far
+ unsigned m_pathsExplored; // number of paths explored so far
+
+ // used for writing .bout files
+ int m_argc;
+ char **m_argv;
+
+public:
+ KleeHandler(int argc, char **argv);
+ ~KleeHandler();
+
+ std::ostream &getInfoStream() const { return *m_infoFile; }
+ unsigned getNumTestCases() { return m_testIndex; }
+ unsigned getNumPathsExplored() { return m_pathsExplored; }
+ void incPathsExplored() { m_pathsExplored++; }
+
+ void setInterpreter(Interpreter *i);
+
+ void processTestCase(const ExecutionState &state,
+ const char *errorMessage,
+ const char *errorSuffix);
+
+ std::string getOutputFilename(const std::string &filename);
+ std::ostream *openOutputFile(const std::string &filename);
+ std::string getTestFilename(const std::string &suffix, unsigned id);
+ std::ostream *openTestFile(const std::string &suffix, unsigned id);
+
+ // load a .out file
+ static void loadOutFile(std::string name,
+ std::vector<unsigned char> &buffer);
+
+ // load a .path file
+ static void loadPathFile(std::string name,
+ std::vector<bool> &buffer);
+
+ static void getOutFiles(std::string path,
+ std::vector<std::string> &results);
+};
+
+KleeHandler::KleeHandler(int argc, char **argv)
+ : m_interpreter(0),
+ m_pathWriter(0),
+ m_symPathWriter(0),
+ m_infoFile(0),
+ m_testIndex(0),
+ m_pathsExplored(0),
+ m_argc(argc),
+ m_argv(argv) {
+ std::string theDir;
+
+ if (OutputDir=="") {
+ llvm::sys::Path directory(InputFile);
+ std::string dirname = "";
+ directory.eraseComponent();
+
+ if (directory.isEmpty())
+ directory.set(".");
+
+ for (int i = 0; ; i++) {
+ char buf[256], tmp[64];
+ sprintf(tmp, "klee-out-%d", i);
+ dirname = tmp;
+ sprintf(buf, "%s/%s", directory.c_str(), tmp);
+ theDir = buf;
+
+ if (DIR *dir = opendir(theDir.c_str())) {
+ closedir(dir);
+ } else {
+ break;
+ }
+ }
+
+ llvm::cerr << "KLEE: output directory = \"" << dirname << "\"\n";
+
+ llvm::sys::Path klee_last(directory);
+ klee_last.appendComponent("klee-last");
+
+ if ((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) {
+ perror("Cannot unlink klee-last");
+ assert(0 && "exiting.");
+ }
+
+ if (symlink(dirname.c_str(), klee_last.c_str()) < 0) {
+ perror("Cannot make symlink");
+ assert(0 && "exiting.");
+ }
+ } else {
+ theDir = OutputDir;
+ }
+
+ sys::Path p(theDir);
+ if (!p.isAbsolute()) {
+ sys::Path cwd = sys::Path::GetCurrentDirectory();
+ cwd.appendComponent(theDir);
+ p = cwd;
+ }
+ strcpy(m_outputDirectory, p.c_str());
+
+ if (mkdir(m_outputDirectory, 0775) < 0) {
+ llvm::cerr << "KLEE: ERROR: Unable to make output directory: \""
+ << m_outputDirectory
+ << "\", refusing to overwrite.\n";
+ exit(1);
+ }
+
+ char fname[1024];
+ snprintf(fname, sizeof(fname), "%s/warnings.txt", m_outputDirectory);
+ klee_warning_file = fopen(fname, "w");
+ assert(klee_warning_file);
+
+ snprintf(fname, sizeof(fname), "%s/messages.txt", m_outputDirectory);
+ klee_message_file = fopen(fname, "w");
+ assert(klee_message_file);
+
+ m_infoFile = openOutputFile("info");
+}
+
+KleeHandler::~KleeHandler() {
+ if (m_pathWriter) delete m_pathWriter;
+ if (m_symPathWriter) delete m_symPathWriter;
+ delete m_infoFile;
+}
+
+void KleeHandler::setInterpreter(Interpreter *i) {
+ m_interpreter = i;
+
+ if (WritePaths) {
+ m_pathWriter = new TreeStreamWriter(getOutputFilename("paths.ts"));
+ assert(m_pathWriter->good());
+ m_interpreter->setPathWriter(m_pathWriter);
+ }
+
+ if (WriteSymPaths) {
+ m_symPathWriter = new TreeStreamWriter(getOutputFilename("symPaths.ts"));
+ assert(m_symPathWriter->good());
+ m_interpreter->setSymbolicPathWriter(m_symPathWriter);
+ }
+}
+
+std::string KleeHandler::getOutputFilename(const std::string &filename) {
+ char outfile[1024];
+ sprintf(outfile, "%s/%s", m_outputDirectory, filename.c_str());
+ return outfile;
+}
+
+std::ostream *KleeHandler::openOutputFile(const std::string &filename) {
+ std::ios::openmode io_mode = std::ios::out | std::ios::trunc
+ | std::ios::binary;
+ std::ostream *f;
+ std::string path = getOutputFilename(filename);
+ f = new std::ofstream(path.c_str(), io_mode);
+ if (!f) {
+ klee_warning("out of memory");
+ } else if (!f->good()) {
+ klee_warning("error opening: %s", filename.c_str());
+ delete f;
+ f = NULL;
+ }
+
+ return f;
+}
+
+std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id) {
+ char filename[1024];
+ sprintf(filename, "test%06d.%s", id, suffix.c_str());
+ return getOutputFilename(filename);
+}
+
+std::ostream *KleeHandler::openTestFile(const std::string &suffix, unsigned id) {
+ char filename[1024];
+ sprintf(filename, "test%06d.%s", id, suffix.c_str());
+ return openOutputFile(filename);
+}
+
+
+/* Outputs all files (.bout, .pc, .cov etc.) describing a test case */
+void KleeHandler::processTestCase(const ExecutionState &state,
+ const char *errorMessage,
+ const char *errorSuffix) {
+ if (errorMessage && ExitOnError) {
+ llvm::cerr << "EXITING ON ERROR: " << errorMessage << "\n";
+ abort();
+ }
+
+ if (!NoOutput) {
+ std::vector< std::pair<std::string, std::vector<unsigned char> > > out;
+ bool success = m_interpreter->getSymbolicSolution(state, out);
+
+ if (!success)
+ klee_warning("unable to get symbolic solution, losing test case");
+
+ double start_time = util::getWallTime();
+
+ unsigned id = ++m_testIndex;
+
+ if (success) {
+ BOut b;
+ b.numArgs = m_argc;
+ b.args = m_argv;
+ b.symArgvs = 0;
+ b.symArgvLen = 0;
+ b.numObjects = out.size();
+ b.objects = new BOutObject[b.numObjects];
+ assert(b.objects);
+ for (unsigned i=0; i<b.numObjects; i++) {
+ BOutObject *o = &b.objects[i];
+ o->name = const_cast<char*>(out[i].first.c_str());
+ o->numBytes = out[i].second.size();
+ o->bytes = new unsigned char[o->numBytes];
+ assert(o->bytes);
+ std::copy(out[i].second.begin(), out[i].second.end(), o->bytes);
+ }
+
+ if (!bOut_toFile(&b, getTestFilename("bout", id).c_str())) {
+ klee_warning("unable to write output test case, losing it");
+ }
+
+ for (unsigned i=0; i<b.numObjects; i++)
+ delete[] b.objects[i].bytes;
+ delete[] b.objects;
+ }
+
+ if (errorMessage) {
+ std::ostream *f = openTestFile(errorSuffix, id);
+ *f << errorMessage;
+ delete f;
+ }
+
+ if (m_pathWriter) {
+ std::vector<unsigned char> concreteBranches;
+ m_pathWriter->readStream(m_interpreter->getPathStreamID(state),
+ concreteBranches);
+ std::ostream *f = openTestFile("path", id);
+ std::copy(concreteBranches.begin(), concreteBranches.end(),
+ std::ostream_iterator<unsigned char>(*f, "\n"));
+ delete f;
+ }
+
+ if (errorMessage || WritePCs) {
+ std::string constraints;
+ m_interpreter->getConstraintLog(state, constraints);
+ std::ostream *f = openTestFile("pc", id);
+ *f << constraints;
+ delete f;
+ }
+
+ if (WriteCVCs) {
+ std::string constraints;
+ m_interpreter->getConstraintLog(state, constraints, true);
+ std::ostream *f = openTestFile("cvc", id);
+ *f << constraints;
+ delete f;
+ }
+
+ if (m_symPathWriter) {
+ std::vector<unsigned char> symbolicBranches;
+ m_symPathWriter->readStream(m_interpreter->getSymbolicPathStreamID(state),
+ symbolicBranches);
+ std::ostream *f = openTestFile("sym.path", id);
+ std::copy(symbolicBranches.begin(), symbolicBranches.end(),
+ std::ostream_iterator<unsigned char>(*f, "\n"));
+ delete f;
+ }
+
+ if (WriteCov) {
+ std::map<const std::string*, std::set<unsigned> > cov;
+ m_interpreter->getCoveredLines(state, cov);
+ std::ostream *f = openTestFile("cov", id);
+ for (std::map<const std::string*, std::set<unsigned> >::iterator
+ it = cov.begin(), ie = cov.end();
+ it != ie; ++it) {
+ for (std::set<unsigned>::iterator
+ it2 = it->second.begin(), ie = it->second.end();
+ it2 != ie; ++it2)
+ *f << *it->first << ":" << *it2 << "\n";
+ }
+ delete f;
+ }
+
+ if (WriteTraces) {
+ std::ostream *f = openTestFile("trace", id);
+ state.exeTraceMgr.printAllEvents(*f);
+ delete f;
+ }
+
+ if (m_testIndex == StopAfterNTests)
+ m_interpreter->setHaltExecution(true);
+
+ if (WriteTestInfo) {
+ double elapsed_time = util::getWallTime() - start_time;
+ std::ostream *f = openTestFile("info", id);
+ *f << "Time to generate test case: "
+ << elapsed_time << "s\n";
+ delete f;
+ }
+ }
+}
+
+ // load a .path file
+void KleeHandler::loadPathFile(std::string name,
+ std::vector<bool> &buffer) {
+ std::ifstream f(name.c_str(), std::ios::in | std::ios::binary);
+
+ if (!f.good())
+ assert(0 && "unable to open path file");
+
+ while (f.good()) {
+ unsigned value;
+ f >> value;
+ buffer.push_back(!!value);
+ f.get();
+ }
+}
+
+void KleeHandler::getOutFiles(std::string path,
+ std::vector<std::string> &results) {
+ llvm::sys::Path p(path);
+ std::set<llvm::sys::Path> contents;
+ std::string error;
+ if (p.getDirectoryContents(contents, &error)) {
+ llvm::cerr << "ERROR: unable to read output directory: " << path << ": " << error << "\n";
+ exit(1);
+ }
+ for (std::set<llvm::sys::Path>::iterator it = contents.begin(),
+ ie = contents.end(); it != ie; ++it) {
+ std::string f = it->toString();
+ if (f.substr(f.size()-5,f.size()) == ".bout") {
+ results.push_back(f);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// main Driver function
+//
+#if ENABLE_STPLOG == 1
+extern "C" void STPLOG_init(const char *);
+#endif
+
+static std::string strip(std::string &in) {
+ unsigned len = in.size();
+ unsigned lead = 0, trail = len;
+ while (lead<len && isspace(in[lead]))
+ ++lead;
+ while (trail>lead && isspace(in[trail-1]))
+ --trail;
+ return in.substr(lead, trail-lead);
+}
+
+static void readArgumentsFromFile(char *file, std::vector<std::string> &results) {
+ std::ifstream f(file);
+ assert(f.is_open() && "unable to open input for reading arguments");
+ while (!f.eof()) {
+ std::string line;
+ std::getline(f, line);
+ line = strip(line);
+ if (!line.empty())
+ results.push_back(line);
+ }
+ f.close();
+}
+
+static void parseArguments(int argc, char **argv) {
+ std::vector<std::string> arguments;
+
+ for (int i=1; i<argc; i++) {
+ if (!strcmp(argv[i],"--read-args") && i+1<argc) {
+ readArgumentsFromFile(argv[++i], arguments);
+ } else {
+ arguments.push_back(argv[i]);
+ }
+ }
+
+ int numArgs = arguments.size() + 1;
+ const char **argArray = new const char*[numArgs+1];
+ argArray[0] = argv[0];
+ argArray[numArgs] = 0;
+ for (int i=1; i<numArgs; i++) {
+ argArray[i] = arguments[i-1].c_str();
+ }
+
+ cl::ParseCommandLineOptions(numArgs, (char**) argArray, " klee\n");
+ delete[] argArray;
+}
+
+
+
+static int initEnv(Module *mainModule) {
+
+ /*
+ nArgcP = alloc oldArgc->getType()
+ nArgvV = alloc oldArgv->getType()
+ store oldArgc nArgcP
+ store oldArgv nArgvP
+ klee_init_environment(nArgcP, nArgvP)
+ nArgc = load nArgcP
+ nArgv = load nArgvP
+ oldArgc->replaceAllUsesWith(nArgc)
+ oldArgv->replaceAllUsesWith(nArgv)
+ */
+
+ Function *mainFn = mainModule->getFunction("main");
+
+ if (mainFn->arg_size() < 2) {
+ llvm::cerr << "Cannot handle ""-init-env"" when main() has less than two arguments.\n";
+ return -1;
+ }
+
+ Instruction* firstInst = mainFn->begin()->begin();
+
+ Value* oldArgc = mainFn->arg_begin();
+ Value* oldArgv = ++mainFn->arg_begin();
+
+ AllocaInst* argcPtr = new AllocaInst(oldArgc->getType(), "argcPtr", firstInst);
+ AllocaInst* argvPtr = new AllocaInst(oldArgv->getType(), "argvPtr", firstInst);
+
+ /* Insert void klee_init_env(int* argc, char*** argv) */
+ std::vector<const Type*> params;
+ params.push_back(Type::Int32Ty);
+ params.push_back(Type::Int32Ty);
+ Function* initEnvFn =
+ cast<Function>(mainModule->getOrInsertFunction("klee_init_env",
+ Type::VoidTy,
+ argcPtr->getType(),
+ argvPtr->getType(),
+ NULL));
+ assert(initEnvFn);
+ std::vector<Value*> args;
+ args.push_back(argcPtr);
+ args.push_back(argvPtr);
+ Instruction* initEnvCall = CallInst::Create(initEnvFn, args.begin(), args.end(),
+ "", firstInst);
+ Value *argc = new LoadInst(argcPtr, "newArgc", firstInst);
+ Value *argv = new LoadInst(argvPtr, "newArgv", firstInst);
+
+ oldArgc->replaceAllUsesWith(argc);
+ oldArgv->replaceAllUsesWith(argv);
+
+ new StoreInst(oldArgc, argcPtr, initEnvCall);
+ new StoreInst(oldArgv, argvPtr, initEnvCall);
+
+ return 0;
+}
+
+
+// This is a terrible hack until we get some real modelling of the
+// system. All we do is check the undefined symbols and m and warn about
+// any "unrecognized" externals and about any obviously unsafe ones.
+
+// Symbols we explicitly support
+static const char *modelledExternals[] = {
+ "_ZTVN10__cxxabiv117__class_type_infoE",
+ "_ZTVN10__cxxabiv120__si_class_type_infoE",
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE",
+
+ // special functions
+ "_assert",
+ "__assert_fail",
+ "__assert_rtn",
+ "calloc",
+ "_exit",
+ "exit",
+ "free",
+ "abort",
+ "klee_abort",
+ "klee_assume",
+ "klee_check_memory_access",
+ "klee_define_fixed_object",
+ "klee_get_errno",
+ "klee_get_value",
+ "klee_get_obj_size",
+ "klee_is_symbolic",
+ "klee_make_symbolic_name",
+ "klee_mark_global",
+ "klee_malloc_n",
+ "klee_merge",
+ "klee_prefer_cex",
+ "klee_print_expr",
+ "klee_print_range",
+ "klee_report_error",
+ "klee_revirt_objects",
+ "klee_set_forking",
+ "klee_silent_exit",
+ "klee_under_constrained",
+ "klee_warning",
+ "klee_warning_once",
+ "klee_alias_function",
+ "llvm.dbg.stoppoint",
+ "llvm.va_start",
+ "llvm.va_end",
+ "malloc",
+ "realloc",
+ "_ZdaPv",
+ "_ZdlPv",
+ "_Znaj",
+ "_Znwj",
+ "_Znam",
+ "_Znwm",
+};
+// Symbols we aren't going to warn about
+static const char *dontCareExternals[] = {
+#if 0
+ // stdio
+ "fprintf",
+ "fflush",
+ "fopen",
+ "fclose",
+ "fputs_unlocked",
+ "putchar_unlocked",
+ "vfprintf",
+ "fwrite",
+ "puts",
+ "printf",
+ "stdin",
+ "stdout",
+ "stderr",
+ "_stdio_term",
+ "__errno_location",
+ "fstat",
+#endif
+
+ // static information, pretty ok to return
+ "getegid",
+ "geteuid",
+ "getgid",
+ "getuid",
+ "getpid",
+ "gethostname",
+ "getpgrp",
+ "getppid",
+ "getpagesize",
+ "getpriority",
+ "getgroups",
+ "getdtablesize",
+ "getrlimit",
+ "getrlimit64",
+ "getcwd",
+ "getwd",
+ "gettimeofday",
+ "uname",
+
+ // fp stuff we just don't worry about yet
+ "frexp",
+ "ldexp",
+ "__isnan",
+ "__signbit",
+};
+// Extra symbols we aren't going to warn about with klee-libc
+static const char *dontCareKlee[] = {
+ "__ctype_b_loc",
+ "__ctype_get_mb_cur_max",
+
+ // io system calls
+ "open",
+ "write",
+ "read",
+ "close",
+};
+// Extra symbols we aren't going to warn about with uclibc
+static const char *dontCareUclibc[] = {
+ "__dso_handle",
+
+ // Don't warn about these since we explicitly commented them out of
+ // uclibc.
+ "printf",
+ "vprintf"
+};
+// Symbols we consider unsafe
+static const char *unsafeExternals[] = {
+ "fork", // oh lord
+ "exec", // heaven help us
+ "error", // calls _exit
+ "raise", // yeah
+ "kill", // mmmhmmm
+};
+#define NELEMS(array) (sizeof(array)/sizeof(array[0]))
+void externalsAndGlobalsCheck(const Module *m) {
+ std::map<std::string, bool> externals;
+ std::set<std::string> modelled(modelledExternals,
+ modelledExternals+NELEMS(modelledExternals));
+ std::set<std::string> dontCare(dontCareExternals,
+ dontCareExternals+NELEMS(dontCareExternals));
+ std::set<std::string> unsafe(unsafeExternals,
+ unsafeExternals+NELEMS(unsafeExternals));
+
+ switch (Libc) {
+ case KleeLibc:
+ dontCare.insert(dontCareKlee, dontCareKlee+NELEMS(dontCareKlee));
+ break;
+ case UcLibc:
+ dontCare.insert(dontCareUclibc,
+ dontCareUclibc+NELEMS(dontCareUclibc));
+ break;
+ case NoLibc: /* silence compiler warning */
+ break;
+ }
+
+
+ if (WithPOSIXRuntime)
+ dontCare.insert("syscall");
+
+ for (Module::const_iterator fnIt = m->begin(), fn_ie = m->end();
+ fnIt != fn_ie; ++fnIt) {
+ if (fnIt->isDeclaration() && !fnIt->use_empty())
+ externals.insert(std::make_pair(fnIt->getName(), false));
+ for (Function::const_iterator bbIt = fnIt->begin(), bb_ie = fnIt->end();
+ bbIt != bb_ie; ++bbIt) {
+ for (BasicBlock::const_iterator it = bbIt->begin(), ie = bbIt->end();
+ it != it; ++it) {
+ if (const CallInst *ci = dyn_cast<CallInst>(it)) {
+ if (isa<InlineAsm>(ci->getCalledValue())) {
+ klee_warning_once(&*fnIt,
+ "function \"%s\" has inline asm",
+ fnIt->getName().c_str());
+ }
+ }
+ }
+ }
+ }
+ for (Module::const_global_iterator
+ it = m->global_begin(), ie = m->global_end();
+ it != ie; ++it)
+ if (it->isDeclaration() && !it->use_empty())
+ externals.insert(std::make_pair(it->getName(), true));
+ // and remove aliases (they define the symbol after global
+ // initialization)
+ for (Module::const_alias_iterator
+ it = m->alias_begin(), ie = m->alias_end();
+ it != ie; ++it) {
+ std::map<std::string, bool>::iterator it2 =
+ externals.find(it->getName());
+ if (it2!=externals.end())
+ externals.erase(it2);
+ }
+
+ std::map<std::string, bool> foundUnsafe;
+ for (std::map<std::string, bool>::iterator
+ it = externals.begin(), ie = externals.end();
+ it != ie; ++it) {
+ const std::string &ext = it->first;
+ if (!modelled.count(ext) && (WarnAllExternals ||
+ !dontCare.count(ext))) {
+ if (unsafe.count(ext)) {
+ foundUnsafe.insert(*it);
+ } else {
+ klee_warning("undefined reference to %s: %s",
+ it->second ? "variable" : "function",
+ ext.c_str());
+ }
+ }
+ }
+
+ for (std::map<std::string, bool>::iterator
+ it = foundUnsafe.begin(), ie = foundUnsafe.end();
+ it != ie; ++it) {
+ const std::string &ext = it->first;
+ klee_warning("undefined reference to %s: %s (UNSAFE)!",
+ it->second ? "variable" : "function",
+ ext.c_str());
+ }
+}
+
+static Interpreter *theInterpreter = 0;
+
+static bool interrupted = false;
+
+// Pulled out so it can be easily called from a debugger.
+extern "C"
+void halt_execution() {
+ theInterpreter->setHaltExecution(true);
+}
+
+extern "C"
+void stop_forking() {
+ theInterpreter->setInhibitForking(true);
+}
+
+static void interrupt_handle() {
+ if (!interrupted && theInterpreter) {
+ llvm::cerr << "KLEE: ctrl-c detected, requesting interpreter to halt.\n";
+ halt_execution();
+ sys::SetInterruptFunction(interrupt_handle);
+ } else {
+ llvm::cerr << "KLEE: ctrl-c detected, exiting.\n";
+ exit(1);
+ }
+ interrupted = true;
+}
+
+// This is a temporary hack. If the running process has access to
+// externals then it can disable interrupts, which screws up the
+// normal "nice" watchdog termination process. We try to request the
+// interpreter to halt using this mechanism as a last resort to save
+// the state data before going ahead and killing it.
+static void halt_via_gdb(int pid) {
+ char buffer[256];
+ sprintf(buffer,
+ "gdb --batch --eval-command=\"p halt_execution()\" "
+ "--eval-command=detach --pid=%d &> /dev/null",
+ pid);
+ // fprintf(stderr, "KLEE: WATCHDOG: running: %s\n", buffer);
+ if (system(buffer)==-1)
+ perror("system");
+}
+
+// returns the end of the string put in buf
+static char *format_tdiff(char *buf, long seconds)
+{
+ assert(seconds >= 0);
+
+ long minutes = seconds / 60; seconds %= 60;
+ long hours = minutes / 60; minutes %= 60;
+ long days = hours / 24; hours %= 24;
+
+ buf = strrchr(buf, '\0');
+ if (days > 0) buf += sprintf(buf, "%ld days, ", days);
+ buf += sprintf(buf, "%02ld:%02ld:%02ld", hours, minutes, seconds);
+ return buf;
+}
+
+#ifndef KLEE_UCLIBC
+static llvm::Module *linkWithUclibc(llvm::Module *mainModule) {
+ fprintf(stderr, "error: invalid libc, no uclibc support!\n");
+ exit(1);
+ return 0;
+}
+#else
+static llvm::Module *linkWithUclibc(llvm::Module *mainModule) {
+ Function *f;
+ // force import of __uClibc_main
+ mainModule->getOrInsertFunction("__uClibc_main",
+ FunctionType::get(Type::VoidTy,
+ std::vector<const Type*>(),
+ true));
+
+ // force various imports
+ if (WithPOSIXRuntime) {
+ mainModule->getOrInsertFunction("realpath",
+ PointerType::getUnqual(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
+ PointerType::getUnqual(Type::Int8Ty),
+ NULL);
+ mainModule->getOrInsertFunction("getutent",
+ PointerType::getUnqual(Type::Int8Ty),
+ NULL);
+ mainModule->getOrInsertFunction("__fgetc_unlocked",
+ Type::Int32Ty,
+ PointerType::getUnqual(Type::Int8Ty),
+ NULL);
+ mainModule->getOrInsertFunction("__fputc_unlocked",
+ Type::Int32Ty,
+ Type::Int32Ty,
+ PointerType::getUnqual(Type::Int8Ty),
+ NULL);
+ }
+
+ f = mainModule->getFunction("__ctype_get_mb_cur_max");
+ if (f) f->setName("_stdlib_mb_cur_max");
+
+ // Strip of asm prefixes for 64 bit versions because they are not
+ // present in uclibc and we want to make sure stuff will get
+ // linked. In the off chance that both prefixed and unprefixed
+ // versions are present in the module, make sure we don't create a
+ // naming conflict.
+ for (Module::iterator fi = mainModule->begin(), fe = mainModule->end();
+ fi != fe;) {
+ Function *f = fi;
+ ++fi;
+ const std::string &name = f->getName();
+ if (name[0]=='\01') {
+ unsigned size = name.size();
+ if (name[size-2]=='6' && name[size-1]=='4') {
+ std::string unprefixed = name.substr(1);
+
+ // See if the unprefixed version exists.
+ if (Function *f2 = mainModule->getFunction(unprefixed)) {
+ f->replaceAllUsesWith(f2);
+ f->eraseFromParent();
+ } else {
+ f->setName(unprefixed);
+ }
+ }
+ }
+ }
+
+ mainModule = klee::linkWithLibrary(mainModule,
+ KLEE_UCLIBC "/lib/libc.a");
+ assert(mainModule && "unable to link with uclibc");
+
+ // more sighs, this is horrible but just a temp hack
+ // f = mainModule->getFunction("__fputc_unlocked");
+ // if (f) f->setName("fputc_unlocked");
+ // f = mainModule->getFunction("__fgetc_unlocked");
+ // if (f) f->setName("fgetc_unlocked");
+
+ Function *f2;
+ f = mainModule->getFunction("open");
+ f2 = mainModule->getFunction("__libc_open");
+ if (f2) {
+ if (f) {
+ f2->replaceAllUsesWith(f);
+ f2->eraseFromParent();
+ } else {
+ f2->setName("open");
+ assert(f2->getName() == "open");
+ }
+ }
+
+ f = mainModule->getFunction("fcntl");
+ f2 = mainModule->getFunction("__libc_fcntl");
+ if (f2) {
+ if (f) {
+ f2->replaceAllUsesWith(f);
+ f2->eraseFromParent();
+ } else {
+ f2->setName("fcntl");
+ assert(f2->getName() == "fcntl");
+ }
+ }
+
+ // XXX we need to rearchitect so this can also be used with
+ // programs externally linked with uclibc.
+
+ // We now need to swap things so that __uClibc_main is the entry
+ // point, in such a way that the arguments are passed to
+ // __uClibc_main correctly. We do this by renaming the user main
+ // and generating a stub function to call __uClibc_main. There is
+ // also an implicit cooperation in that runFunctionAsMain sets up
+ // the environment arguments to what uclibc expects (following
+ // argv), since it does not explicitly take an envp argument.
+ Function *userMainFn = mainModule->getFunction("main");
+ assert(userMainFn && "unable to get user main");
+ Function *uclibcMainFn = mainModule->getFunction("__uClibc_main");
+ assert(uclibcMainFn && "unable to get uclibc main");
+ userMainFn->setName("__user_main");
+
+ const FunctionType *ft = uclibcMainFn->getFunctionType();
+ assert(ft->getNumParams() == 7);
+
+ std::vector<const Type*> fArgs;
+ fArgs.push_back(ft->getParamType(1)); // argc
+ fArgs.push_back(ft->getParamType(2)); // argv
+ Function *stub = Function::Create(FunctionType::get(Type::Int32Ty, fArgs, false),
+ GlobalVariable::ExternalLinkage,
+ "main",
+ mainModule);
+ BasicBlock *bb = BasicBlock::Create("entry", stub);
+
+ std::vector<llvm::Value*> args;
+ args.push_back(llvm::ConstantExpr::getBitCast(userMainFn,
+ ft->getParamType(0)));
+ args.push_back(stub->arg_begin()); // argc
+ args.push_back(++stub->arg_begin()); // argv
+ args.push_back(Constant::getNullValue(ft->getParamType(3))); // app_init
+ args.push_back(Constant::getNullValue(ft->getParamType(4))); // app_fini
+ args.push_back(Constant::getNullValue(ft->getParamType(5))); // rtld_fini
+ args.push_back(Constant::getNullValue(ft->getParamType(6))); // stack_end
+ CallInst::Create(uclibcMainFn, args.begin(), args.end(), "", bb);
+
+ new UnreachableInst(bb);
+
+ return mainModule;
+}
+#endif
+
+int main(int argc, char **argv, char **envp) {
+#if ENABLE_STPLOG == 1
+ STPLOG_init("stplog.c");
+#endif
+
+ atexit(llvm_shutdown); // Call llvm_shutdown() on exit.
+ parseArguments(argc, argv);
+ sys::PrintStackTraceOnErrorSignal();
+
+ if (Watchdog) {
+ if (MaxTime==0) {
+ klee_error("--watchdog used without --max-time");
+ }
+
+ int pid = fork();
+ if (pid<0) {
+ klee_error("unable to fork watchdog");
+ } else if (pid) {
+ fprintf(stderr, "KLEE: WATCHDOG: watching %d\n", pid);
+ fflush(stderr);
+
+ double nextStep = util::getWallTime() + MaxTime*1.1;
+ int level = 0;
+
+ // Simple stupid code...
+ while (1) {
+ sleep(1);
+
+ int status, res = waitpid(pid, &status, WNOHANG);
+
+ if (res < 0) {
+ if (errno==ECHILD) { // No child, no need to watch but
+ // return error since we didn't catch
+ // the exit.
+ fprintf(stderr, "KLEE: watchdog exiting (no child)\n");
+ return 1;
+ } else if (errno!=EINTR) {
+ perror("watchdog waitpid");
+ exit(1);
+ }
+ } else if (res==pid && WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ } else {
+ double time = util::getWallTime();
+
+ if (time > nextStep) {
+ ++level;
+
+ if (level==1) {
+ fprintf(stderr, "KLEE: WATCHDOG: time expired, attempting halt via INT\n");
+ kill(pid, SIGINT);
+ } else if (level==2) {
+ fprintf(stderr, "KLEE: WATCHDOG: time expired, attempting halt via gdb\n");
+ halt_via_gdb(pid);
+ } else {
+ fprintf(stderr, "KLEE: WATCHDOG: kill(9)ing child (I tried to be nice)\n");
+ kill(pid, SIGKILL);
+ return 1; // what more can we do
+ }
+
+ // Ideally this triggers a dump, which may take a while,
+ // so try and give the process extra time to clean up.
+ nextStep = util::getWallTime() + std::max(15., MaxTime*.1);
+ }
+ }
+ }
+
+ return 0;
+ }
+ }
+
+ sys::SetInterruptFunction(interrupt_handle);
+
+ // Load the bytecode...
+ std::string ErrorMsg;
+ ModuleProvider *MP = 0;
+ if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile, &ErrorMsg)) {
+ MP = getBitcodeModuleProvider(Buffer, &ErrorMsg);
+ if (!MP) delete Buffer;
+ }
+
+ if (!MP)
+ klee_error("error loading program '%s': %s", InputFile.c_str(), ErrorMsg.c_str());
+
+ Module *mainModule = MP->materializeModule();
+ MP->releaseModule();
+ delete MP;
+
+ assert(mainModule && "unable to materialize");
+
+ if (WithPOSIXRuntime)
+ InitEnv = true;
+
+ if (InitEnv) {
+ int r = initEnv(mainModule);
+ if (r != 0)
+ return r;
+ }
+
+ llvm::sys::Path LibraryDir(KLEE_DIR "/" RUNTIME_CONFIGURATION "/lib");
+ Interpreter::ModuleOptions Opts(LibraryDir.c_str(),
+ /*Optimize=*/OptimizeModule,
+ /*CheckDivZero=*/CheckDivZero);
+
+ switch (Libc) {
+ case NoLibc: /* silence compiler warning */
+ break;
+
+ case KleeLibc: {
+ // FIXME: Find a reasonable solution for this.
+ llvm::sys::Path Path(Opts.LibraryDir);
+ Path.appendComponent("libklee-libc.bca");
+ mainModule = klee::linkWithLibrary(mainModule, Path.c_str());
+ assert(mainModule && "unable to link with klee-libc");
+ break;
+ }
+
+ case UcLibc:
+ mainModule = linkWithUclibc(mainModule);
+ break;
+ }
+
+ if (WithPOSIXRuntime) {
+ llvm::sys::Path Path(Opts.LibraryDir);
+ Path.appendComponent("libkleeRuntimePOSIX.bca");
+ klee_message("NOTE: Using model: %s", Path.c_str());
+ mainModule = klee::linkWithLibrary(mainModule, Path.c_str());
+ assert(mainModule && "unable to link with simple model");
+ }
+
+ // Get the desired main function. klee_main initializes uClibc
+ // locale and other data and then calls main.
+ Function *mainFn = mainModule->getFunction("main");
+ if (!mainFn) {
+ llvm::cerr << "'main' function not found in module.\n";
+ return -1;
+ }
+
+ // FIXME: Change me to std types.
+ int pArgc;
+ char **pArgv;
+ char **pEnvp;
+ if (Environ != "") {
+ std::vector<std::string> items;
+ std::ifstream f(Environ.c_str());
+ if (!f.good())
+ klee_error("unable to open --environ file: %s", Environ.c_str());
+ while (!f.eof()) {
+ std::string line;
+ std::getline(f, line);
+ line = strip(line);
+ if (!line.empty())
+ items.push_back(line);
+ }
+ f.close();
+ pEnvp = new char *[items.size()+1];
+ unsigned i=0;
+ for (; i != items.size(); ++i)
+ pEnvp[i] = strdup(items[i].c_str());
+ pEnvp[i] = 0;
+ } else {
+ pEnvp = envp;
+ }
+
+ pArgc = InputArgv.size() + 1;
+ pArgv = new char *[pArgc];
+ for (unsigned i=0; i<InputArgv.size()+1; i++) {
+ std::string &arg = (i==0 ? InputFile : InputArgv[i-1]);
+ unsigned size = arg.size() + 1;
+ char *pArg = new char[size];
+
+ std::copy(arg.begin(), arg.end(), pArg);
+ pArg[size - 1] = 0;
+
+ pArgv[i] = pArg;
+ }
+
+ std::vector<bool> replayPath;
+
+ if (ReplayPathFile != "") {
+ KleeHandler::loadPathFile(ReplayPathFile, replayPath);
+ }
+
+ Interpreter::InterpreterOptions IOpts;
+ IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic;
+ KleeHandler *handler = new KleeHandler(pArgc, pArgv);
+ Interpreter *interpreter =
+ theInterpreter = Interpreter::create(IOpts, handler);
+ handler->setInterpreter(interpreter);
+
+ std::ostream &infoFile = handler->getInfoStream();
+ for (int i=0; i<argc; i++) {
+ infoFile << argv[i] << (i+1<argc ? " ":"\n");
+ }
+ infoFile << "PID: " << getpid() << "\n";
+
+ const Module *finalModule =
+ interpreter->setModule(mainModule, Opts);
+ externalsAndGlobalsCheck(finalModule);
+
+ if (ReplayPathFile != "") {
+ interpreter->setReplayPath(&replayPath);
+ }
+
+ char buf[256];
+ time_t t[2];
+ t[0] = time(NULL);
+ strftime(buf, sizeof(buf), "Started: %Y-%m-%d %H:%M:%S\n", localtime(&t[0]));
+ infoFile << buf;
+ infoFile.flush();
+
+ if (!ReplayOutDir.empty() || !ReplayOutFile.empty()) {
+ assert(SeedOutFile.empty());
+ assert(SeedOutDir.empty());
+
+ std::vector<std::string> outFiles = ReplayOutFile;
+ for (std::vector<std::string>::iterator
+ it = ReplayOutDir.begin(), ie = ReplayOutDir.end();
+ it != ie; ++it)
+ KleeHandler::getOutFiles(*it, outFiles);
+ std::vector<BOut*> bOuts;
+ for (std::vector<std::string>::iterator
+ it = outFiles.begin(), ie = outFiles.end();
+ it != ie; ++it) {
+ BOut *out = bOut_fromFile(it->c_str());
+ if (out) {
+ bOuts.push_back(out);
+ } else {
+ llvm::cerr << "KLEE: unable to open: " << *it << "\n";
+ }
+ }
+
+ if (RunInDir != "") {
+ int res = chdir(RunInDir.c_str());
+ if (res < 0) {
+ klee_error("Unable to change directory to: %s", RunInDir.c_str());
+ }
+ }
+
+ unsigned i=0;
+ for (std::vector<BOut*>::iterator
+ it = bOuts.begin(), ie = bOuts.end();
+ it != ie; ++it) {
+ BOut *out = *it;
+ interpreter->setReplayOut(out);
+ llvm::cerr << "KLEE: replaying: " << *it << " (" << bOut_numBytes(out) << " bytes)"
+ << " (" << ++i << "/" << outFiles.size() << ")\n";
+ // XXX should put envp in .bout ?
+ interpreter->runFunctionAsMain(mainFn, out->numArgs, out->args, pEnvp);
+ if (interrupted) break;
+ }
+ interpreter->setReplayOut(0);
+ while (!bOuts.empty()) {
+ bOut_free(bOuts.back());
+ bOuts.pop_back();
+ }
+ } else {
+ std::vector<BOut *> seeds;
+ for (std::vector<std::string>::iterator
+ it = SeedOutFile.begin(), ie = SeedOutFile.end();
+ it != ie; ++it) {
+ BOut *out = bOut_fromFile(it->c_str());
+ if (!out) {
+ llvm::cerr << "KLEE: unable to open: " << *it << "\n";
+ exit(1);
+ }
+ seeds.push_back(out);
+ }
+ for (std::vector<std::string>::iterator
+ it = SeedOutDir.begin(), ie = SeedOutDir.end();
+ it != ie; ++it) {
+ std::vector<std::string> outFiles;
+ KleeHandler::getOutFiles(*it, outFiles);
+ for (std::vector<std::string>::iterator
+ it2 = outFiles.begin(), ie = outFiles.end();
+ it2 != ie; ++it2) {
+ BOut *out = bOut_fromFile(it2->c_str());
+ if (!out) {
+ llvm::cerr << "KLEE: unable to open: " << *it2 << "\n";
+ exit(1);
+ }
+ seeds.push_back(out);
+ }
+ if (outFiles.empty()) {
+ llvm::cerr << "KLEE: seeds directory is empty: " << *it << "\n";
+ exit(1);
+ }
+ }
+
+ if (!seeds.empty()) {
+ llvm::cerr << "KLEE: using " << seeds.size() << " seeds\n";
+ interpreter->useSeeds(&seeds);
+ }
+ if (RunInDir != "") {
+ int res = chdir(RunInDir.c_str());
+ if (res < 0) {
+ klee_error("Unable to change directory to: %s", RunInDir.c_str());
+ }
+ }
+ interpreter->runFunctionAsMain(mainFn, pArgc, pArgv, pEnvp);
+
+ while (!seeds.empty()) {
+ bOut_free(seeds.back());
+ seeds.pop_back();
+ }
+ }
+
+ t[1] = time(NULL);
+ strftime(buf, sizeof(buf), "Finished: %Y-%m-%d %H:%M:%S\n", localtime(&t[1]));
+ infoFile << buf;
+
+ strcpy(buf, "Elapsed: ");
+ strcpy(format_tdiff(buf, t[1] - t[0]), "\n");
+ infoFile << buf;
+
+ // Free all the args.
+ for (unsigned i=0; i<InputArgv.size()+1; i++)
+ delete[] pArgv[i];
+ delete[] pArgv;
+
+ delete interpreter;
+
+ uint64_t queries =
+ *theStatisticManager->getStatisticByName("Queries");
+ uint64_t queriesValid =
+ *theStatisticManager->getStatisticByName("QueriesValid");
+ uint64_t queriesInvalid =
+ *theStatisticManager->getStatisticByName("QueriesInvalid");
+ uint64_t queryCounterexamples =
+ *theStatisticManager->getStatisticByName("QueriesCEX");
+ uint64_t queryConstructs =
+ *theStatisticManager->getStatisticByName("QueriesConstructs");
+ uint64_t instructions =
+ *theStatisticManager->getStatisticByName("Instructions");
+ uint64_t forks =
+ *theStatisticManager->getStatisticByName("Forks");
+
+ handler->getInfoStream()
+ << "KLEE: done: explored paths = " << 1 + forks << "\n";
+
+ // Write some extra information in the info file which users won't
+ // necessarily care about or understand.
+ if (queries)
+ handler->getInfoStream()
+ << "KLEE: done: avg. constructs per query = "
+ << queryConstructs / queries << "\n";
+ handler->getInfoStream()
+ << "KLEE: done: total queries = " << queries << "\n"
+ << "KLEE: done: valid queries = " << queriesValid << "\n"
+ << "KLEE: done: invalid queriers = " << queriesInvalid << "\n"
+ << "KLEE: done: query cex = " << queryCounterexamples << "\n";
+
+ std::stringstream stats;
+ stats << "KLEE: done: total instructions = "
+ << instructions << "\n";
+ stats << "KLEE: done: completed paths = "
+ << handler->getNumPathsExplored() << "\n";
+ stats << "KLEE: done: generated tests = "
+ << handler->getNumTestCases() << "\n";
+ llvm::cerr << stats.str();
+ handler->getInfoStream() << stats.str();
+
+ delete handler;
+
+ return 0;
+}
Added: klee/trunk/unittests/Expr/ExprTest.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/unittests/Expr/ExprTest.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/unittests/Expr/ExprTest.cpp (added)
+++ klee/trunk/unittests/Expr/ExprTest.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,112 @@
+//===-- ExprTest.cpp ------------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "klee/Expr.h"
+
+using namespace klee;
+
+namespace {
+
+ref<Expr> getConstant(int value, Expr::Width width) {
+ int64_t ext = value;
+ uint64_t trunc = ext & (((uint64_t) -1LL) >> (64 - width));
+ return ConstantExpr::create(trunc, width);
+}
+
+TEST(ExprTest, BasicConstruction) {
+ EXPECT_EQ(ref<Expr>(0, 32),
+ SubExpr::create(ref<Expr>(10, 32),
+ ref<Expr>(10, 32)));
+}
+
+TEST(ExprTest, ConcatExtract) {
+ Array *array = new Array(0, 1, 256);
+ ref<Expr> read8 = Expr::createTempRead(array, 8);
+ Array *array2 = new Array(0, 2, 256);
+ ref<Expr> read8_2 = Expr::createTempRead(array2, 8);
+ ref<Expr> c100 = getConstant(100, 8);
+
+ ref<Expr> concat1 = ConcatExpr::create4(read8, read8, c100, read8_2);
+ EXPECT_EQ(2U, concat1.getNumKids());
+ EXPECT_EQ(2U, concat1.getKid(1).getNumKids());
+ EXPECT_EQ(2U, concat1.getKid(1).getKid(1).getNumKids());
+
+ ref<Expr> extract1 = ExtractExpr::create(concat1, 8, 16);
+ EXPECT_EQ(Expr::Concat, extract1.getKind());
+ EXPECT_EQ(read8, extract1.getKid(0));
+ EXPECT_EQ(c100, extract1.getKid(1));
+
+ ref<Expr> extract2 = ExtractExpr::create(concat1, 6, 26);
+ EXPECT_EQ( Expr::Concat, extract2.getKind());
+ EXPECT_EQ( read8, extract2.getKid(0));
+ EXPECT_EQ( Expr::Concat, extract2.getKid(1).getKind());
+ EXPECT_EQ( read8, extract2.getKid(1).getKid(0));
+ EXPECT_EQ( Expr::Concat, extract2.getKid(1).getKid(1).getKind());
+ EXPECT_EQ( c100, extract2.getKid(1).getKid(1).getKid(0));
+ EXPECT_EQ( Expr::Extract, extract2.getKid(1).getKid(1).getKid(1).getKind());
+
+ ref<Expr> extract3 = ExtractExpr::create(concat1, 24, 1);
+ EXPECT_EQ(Expr::Extract, extract3.getKind());
+
+ ref<Expr> extract4 = ExtractExpr::create(concat1, 27, 2);
+ EXPECT_EQ(Expr::Extract, extract4.getKind());
+ const ExtractExpr* tmp = dyn_ref_cast<ExtractExpr>(extract4);
+ EXPECT_EQ(3U, tmp->offset);
+ EXPECT_EQ(2U, tmp->getWidth());
+
+ ref<Expr> extract5 = ExtractExpr::create(concat1, 17, 5);
+ EXPECT_EQ(Expr::Extract, extract5.getKind());
+
+ ref<Expr> extract6 = ExtractExpr::create(concat1, 3, 26);
+ EXPECT_EQ(Expr::Concat, extract6.getKind());
+ EXPECT_EQ(Expr::Extract, extract6.getKid(0).getKind());
+ EXPECT_EQ(Expr::Concat, extract6.getKid(1).getKind());
+ EXPECT_EQ(read8, extract6.getKid(1).getKid(0));
+ EXPECT_EQ(Expr::Concat, extract6.getKid(1).getKid(1).getKind());
+ EXPECT_EQ(c100, extract6.getKid(1).getKid(1).getKid(0));
+ EXPECT_EQ(Expr::Extract, extract6.getKid(1).getKid(1).getKid(1).getKind());
+
+ ref<Expr> concat10 = ConcatExpr::create4(read8, c100, c100, read8);
+ ref<Expr> extract10 = ExtractExpr::create(concat10, 8, 16);
+ EXPECT_EQ(Expr::Constant, extract10.getKind());
+}
+
+TEST(ExprTest, ExtractConcat) {
+ Array *array = new Array(0, 3, 256);
+ ref<Expr> read64 = Expr::createTempRead(array, 64);
+
+ Array *array2 = new Array(0, 4, 256);
+ ref<Expr> read8_2 = Expr::createTempRead(array2, 8);
+
+ ref<Expr> extract1 = ExtractExpr::create(read64, 36, 4);
+ ref<Expr> extract2 = ExtractExpr::create(read64, 32, 4);
+
+ ref<Expr> extract3 = ExtractExpr::create(read64, 12, 3);
+ ref<Expr> extract4 = ExtractExpr::create(read64, 10, 2);
+ ref<Expr> extract5 = ExtractExpr::create(read64, 2, 8);
+
+ ref<Expr> kids1[6] = { extract1, extract2,
+ read8_2,
+ extract3, extract4, extract5 };
+ ref<Expr> concat1 = ConcatExpr::createN(6, kids1);
+ EXPECT_EQ(29U, concat1.getWidth());
+
+ ref<Expr> extract6 = ExtractExpr::create(read8_2, 2, 5);
+ ref<Expr> extract7 = ExtractExpr::create(read8_2, 1, 1);
+
+ ref<Expr> kids2[3] = { extract1, extract6, extract7 };
+ ref<Expr> concat2 = ConcatExpr::createN(3, kids2);
+ EXPECT_EQ(10U, concat2.getWidth());
+ EXPECT_EQ(Expr::Extract, concat2.getKid(0).getKind());
+ EXPECT_EQ(Expr::Extract, concat2.getKid(1).getKind());
+}
+
+}
Added: klee/trunk/unittests/Expr/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/unittests/Expr/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/unittests/Expr/Makefile (added)
+++ klee/trunk/unittests/Expr/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+##===- unittests/Expr/Makefile -----------------------------*- Makefile -*-===##
+
+LEVEL := ../..
+TESTNAME := Expr
+USEDLIBS := kleaverExpr.a kleeBasic.a
+LINK_COMPONENTS := support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
+LIBS += -lstp
Added: klee/trunk/unittests/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/unittests/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/unittests/Makefile (added)
+++ klee/trunk/unittests/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,18 @@
+##===- unittests/Makefile ----------------------------------*- Makefile -*-===##
+
+LEVEL = ..
+
+include $(LEVEL)/Makefile.config
+
+LIBRARYNAME = UnitTestMain
+BUILD_ARCHIVE = 1
+CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include/
+CPP.Flags += -Wno-variadic-macros
+
+# FIXME: Parallel dirs is broken?
+DIRS = Expr Solver
+
+include $(LEVEL)/Makefile.common
+
+clean::
+ $(Verb) $(RM) -f *Tests
Propchange: klee/trunk/unittests/Makefile
------------------------------------------------------------------------------
svn:executable = *
Added: klee/trunk/unittests/Solver/Makefile
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/unittests/Solver/Makefile?rev=72205&view=auto
==============================================================================
--- klee/trunk/unittests/Solver/Makefile (added)
+++ klee/trunk/unittests/Solver/Makefile Wed May 20 23:36:41 2009
@@ -0,0 +1,11 @@
+##===- unittests/Solver/Makefile ---------------------------*- Makefile -*-===##
+
+LEVEL := ../..
+TESTNAME := Solver
+USEDLIBS := kleaverSolver.a kleaverExpr.a kleeSupport.a kleeBasic.a
+LINK_COMPONENTS := support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
+LIBS += -lstp
Added: klee/trunk/unittests/Solver/SolverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/unittests/Solver/SolverTest.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/unittests/Solver/SolverTest.cpp (added)
+++ klee/trunk/unittests/Solver/SolverTest.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,164 @@
+//===-- SolverTest.cpp ----------------------------------------------------===//
+//
+// The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "klee/Constraints.h"
+#include "klee/Expr.h"
+#include "klee/Solver.h"
+
+using namespace klee;
+
+namespace {
+
+const int g_constants[] = { -1, 1, 4, 17, 0 };
+const Expr::Width g_types[] = { Expr::Bool,
+ Expr::Int8,
+ Expr::Int16,
+ Expr::Int32,
+ Expr::Int64 };
+
+ref<Expr> getConstant(int value, Expr::Width width) {
+ int64_t ext = value;
+ uint64_t trunc = ext & (((uint64_t) -1LL) >> (64 - width));
+ return ConstantExpr::create(trunc, width);
+}
+
+
+template<class T>
+void testOperation(Solver &solver,
+ int value,
+ Expr::Width operandWidth,
+ Expr::Width resultWidth) {
+ std::vector<Expr::CreateArg> symbolicArgs;
+
+ for (unsigned i = 0; i < T::numKids; i++) {
+ if (!T::isValidKidWidth(i, operandWidth))
+ return;
+
+ unsigned size = Expr::getMinBytesForWidth(operandWidth);
+ static unsigned id = 0;
+ Array *array = new Array(0, ++id, size);
+ symbolicArgs.push_back(Expr::CreateArg(Expr::createTempRead(array,
+ operandWidth)));
+ }
+
+ if (T::needsResultType())
+ symbolicArgs.push_back(Expr::CreateArg(resultWidth));
+
+ ref<Expr> fullySymbolicExpr = Expr::createFromKind(T::kind, symbolicArgs);
+
+ // For each kid, replace the kid with a constant value and verify
+ // that the fully symbolic expression is equivalent to it when the
+ // replaced value is appropriated constrained.
+ for (unsigned kid = 0; kid < T::numKids; kid++) {
+ std::vector<Expr::CreateArg> partiallyConstantArgs(symbolicArgs);
+ for (unsigned i = 0; i < T::numKids; i++)
+ if (i==kid)
+ partiallyConstantArgs[i] = getConstant(value, operandWidth);
+
+ ref<Expr> expr =
+ NotOptimizedExpr::create(EqExpr::create(partiallyConstantArgs[kid].expr,
+ symbolicArgs[kid].expr));
+
+ ref<Expr> partiallyConstantExpr =
+ Expr::createFromKind(T::kind, partiallyConstantArgs);
+
+ ref<Expr> queryExpr = EqExpr::create(fullySymbolicExpr,
+ partiallyConstantExpr);
+
+ ConstraintManager constraints;
+ constraints.addConstraint(expr);
+ bool res;
+ bool success = solver.mustBeTrue(Query(constraints, queryExpr), res);
+ EXPECT_EQ(true, success) << "Constraint solving failed";
+
+ if (success) {
+ EXPECT_EQ(true, res) << "Evaluation failed!\n"
+ << "query " << queryExpr
+ << " with " << expr;
+ }
+ }
+}
+
+template<class T>
+void testOpcode(Solver &solver, bool tryBool = true, bool tryZero = true,
+ unsigned maxWidth = 64) {
+ for (unsigned j=0; j<sizeof(g_types)/sizeof(g_types[0]); j++) {
+ Expr::Width type = g_types[j];
+
+ if (type > maxWidth) continue;
+
+ for (unsigned i=0; i<sizeof(g_constants)/sizeof(g_constants[0]); i++) {
+ int value = g_constants[i];
+ if (!tryZero && !value) continue;
+ if (type == Expr::Bool && !tryBool) continue;
+
+ if (!T::needsResultType()) {
+ testOperation<T>(solver, value, type, type);
+ continue;
+ }
+
+ for (unsigned k=0; k<sizeof(g_types)/sizeof(g_types[0]); k++) {
+ Expr::Width resultType = g_types[k];
+
+ // nasty hack to give only Trunc/ZExt/SExt the right types
+ if (T::kind == Expr::SExt || T::kind == Expr::ZExt) {
+ if (Expr::getMinBytesForWidth(type) >=
+ Expr::getMinBytesForWidth(resultType))
+ continue;
+ }
+
+ testOperation<T>(solver, value, type, resultType);
+ }
+ }
+ }
+}
+
+TEST(SolverTest, Evaluation) {
+ STPSolver *stpSolver = new STPSolver(true);
+ Solver *solver = stpSolver;
+
+ solver = createCexCachingSolver(solver);
+ solver = createCachingSolver(solver);
+ solver = createIndependentSolver(solver);
+
+ testOpcode<SelectExpr>(*solver);
+ testOpcode<ZExtExpr>(*solver);
+ testOpcode<SExtExpr>(*solver);
+
+ testOpcode<AddExpr>(*solver);
+ testOpcode<SubExpr>(*solver);
+ testOpcode<MulExpr>(*solver, false, true, 8);
+ testOpcode<SDivExpr>(*solver, false, false, 8);
+ testOpcode<UDivExpr>(*solver, false, false, 8);
+ testOpcode<SRemExpr>(*solver, false, false, 8);
+ testOpcode<URemExpr>(*solver, false, false, 8);
+ testOpcode<ShlExpr>(*solver, false);
+ testOpcode<LShrExpr>(*solver, false);
+ testOpcode<AShrExpr>(*solver, false);
+ testOpcode<AndExpr>(*solver);
+ testOpcode<OrExpr>(*solver);
+ testOpcode<XorExpr>(*solver);
+
+ testOpcode<EqExpr>(*solver);
+ testOpcode<NeExpr>(*solver);
+ testOpcode<UltExpr>(*solver);
+ testOpcode<UleExpr>(*solver);
+ testOpcode<UgtExpr>(*solver);
+ testOpcode<UgeExpr>(*solver);
+ testOpcode<SltExpr>(*solver);
+ testOpcode<SleExpr>(*solver);
+ testOpcode<SgtExpr>(*solver);
+ testOpcode<SgeExpr>(*solver);
+
+ delete solver;
+}
+
+}
Added: klee/trunk/unittests/TestMain.cpp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/unittests/TestMain.cpp?rev=72205&view=auto
==============================================================================
--- klee/trunk/unittests/TestMain.cpp (added)
+++ klee/trunk/unittests/TestMain.cpp Wed May 20 23:36:41 2009
@@ -0,0 +1,15 @@
+//===--- unittests/TestMain.cpp - unittest driver -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+int main(int argc, char **argv) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
Added: klee/trunk/utils/emacs/klee-pc-mode.el
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/utils/emacs/klee-pc-mode.el?rev=72205&view=auto
==============================================================================
--- klee/trunk/utils/emacs/klee-pc-mode.el (added)
+++ klee/trunk/utils/emacs/klee-pc-mode.el Wed May 20 23:36:41 2009
@@ -0,0 +1,64 @@
+(provide 'klee-pc-mode)
+
+(require 'font-lock)
+
+(defvar klee-pc-mode-syntax-table nil
+ "Syntax table used while in ft-bt mode.")
+
+;;; --------------------------------------------------
+;;;setup the syntax table
+;;; --------------------------------------------------
+(unless klee-pc-mode-syntax-table
+ (setq klee-pc-mode-syntax-table (make-syntax-table))
+ ;;misc
+ (modify-syntax-entry ?\_ "w" klee-pc-mode-syntax-table)
+ (modify-syntax-entry ?\. "." klee-pc-mode-syntax-table))
+
+;;;------------------------------------------------------------
+;;; local keymap
+;;;------------------------------------------------------------
+
+(defvar klee-pc-local-keymap nil)
+
+;;; --------------------------------------------------
+;;; set keywords
+;;; --------------------------------------------------
+
+(defvar klee-pc-mode-font-lock-keywords
+ (list
+ ;; Comments
+ '("#.*" . font-lock-comment-face)
+ ;; Identifiers
+ '("%[_a-zA-Z][a-zA-Z_.0-9]*" . font-lock-variable-name-face)
+ ;; Numbers
+ '("[+-]?0b[01_]+" . font-lock-preprocessor-face)
+ '("[+-]?0o[0-7_]+" . font-lock-preprocessor-face)
+ '("[+-]?0x[a-zA-Z0-9_]+" . font-lock-preprocessor-face)
+ '("[+-]?[0-9]+" . font-lock-preprocessor-face)
+ ;; Keywords
+ '("\\bdef\\b\\|\\bvar\\b\\|\\btrue\\b\\|\\barray\\b\\|\\bfalse\\b\\|\\bquery\\b\\|\\bdefine\\b\\|\\bdeclare\\b" . font-lock-keyword-face)
+ )
+ "klee-PC mode keywords")
+
+;;; --------------------------------------------------
+;;; major mode function
+;;; --------------------------------------------------
+(defun klee-pc-mode ()
+ "Switch to the klee-pc major mode"
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'klee-pc-mode)
+ (setq mode-name "klee-pc")
+
+ ;; handle keymap
+ (use-local-map klee-pc-local-keymap)
+
+ ;;handle syntax table
+ (set-syntax-table klee-pc-mode-syntax-table)
+ ;;handle fontlock
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(klee-pc-mode-font-lock-keywords
+ nil t))
+
+ ;;handle hook
+ (run-hooks 'klee-pc-mode-hook))
Added: klee/trunk/utils/valgrind/README.txt
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/utils/valgrind/README.txt?rev=72205&view=auto
==============================================================================
--- klee/trunk/utils/valgrind/README.txt (added)
+++ klee/trunk/utils/valgrind/README.txt Wed May 20 23:36:41 2009
@@ -0,0 +1,2 @@
+A few valgrind suppression files for known leaks. The LLVM ones may be
+fixed by now.
Added: klee/trunk/utils/valgrind/valgrind-llvm.supp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/utils/valgrind/valgrind-llvm.supp?rev=72205&view=auto
==============================================================================
--- klee/trunk/utils/valgrind/valgrind-llvm.supp (added)
+++ klee/trunk/utils/valgrind/valgrind-llvm.supp Wed May 20 23:36:41 2009
@@ -0,0 +1,24 @@
+{
+ LLVM:Tmp1
+ Memcheck:Leak
+ fun:_vgrZU_libstdcZpZpZa__Znwj
+ fun:_ZN4llvm*
+}
+{
+ LLVM:Tmp2
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:_ZN4llvm*
+}
+{
+ LLVM:Tmp3
+ Memcheck:Leak
+ fun:*nwj*
+ fun:*llvm*
+}
+{
+ LLVM:Tmp4
+ Memcheck:Leak
+ fun:malloc
+ fun:*llvm*
+}
Added: klee/trunk/utils/valgrind/valgrind-stp.supp
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/utils/valgrind/valgrind-stp.supp?rev=72205&view=auto
==============================================================================
--- klee/trunk/utils/valgrind/valgrind-stp.supp (added)
+++ klee/trunk/utils/valgrind/valgrind-stp.supp Wed May 20 23:36:41 2009
@@ -0,0 +1,32 @@
+{
+ STP:BeevMgr
+ Memcheck:Leak
+ fun:_vgrZU_libstdcZpZpZa__Znwj
+ fun:_ZN4BEEV7BeevMgr*
+}
+{
+ STP:BeevMgr:strdup
+ Memcheck:Leak
+ fun:_vgrZU_libcZdsoZa_malloc
+ fun:strdup
+ fun:_ZN4BEEV7BeevMgr*
+}
+{
+ STP:c_interface
+ Memcheck:Leak
+ fun:_vgrZU_libstdcZpZpZa__Znwj
+ fun:vc_*
+}
+{
+ STP:BeevMgr:vector
+ Memcheck:Leak
+ fun:_vgrZU_libstdcZpZpZa__Znwj
+ fun:_ZNSt6vector*
+ fun:_ZN4BEEV7BeevMgr*
+}
+{
+ LLVM:Tmp1
+ Memcheck:Leak
+ fun:_vgrZU_libstdcZpZpZa__Znwj
+ fun:_ZN4llvm*
+}
Added: klee/trunk/www/Examples.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/Examples.html?rev=72205&view=auto
==============================================================================
--- klee/trunk/www/Examples.html (added)
+++ klee/trunk/www/Examples.html Wed May 20 23:36:41 2009
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+ <title>KLEE - Examples</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>KLEE Examples</h1>
+
+<p>FIXME: Intro.</p>
+
+<h2>Basic Sort Example</h2>
+
+<p>FIXME: Write.</p>
+
+<h2>FIXME: More complicated example</h2>
+
+<p>FIXME: Write: show the important klee.h functions.</p>
+
+<p>FIXME: Write: show the important klee tools.</p>
+
+<p>FIXME: Write: show the important klee options.</p>
+
+</div>
+</body>
+</html>
Added: klee/trunk/www/GetInvolved.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/GetInvolved.html?rev=72205&view=auto
==============================================================================
--- klee/trunk/www/GetInvolved.html (added)
+++ klee/trunk/www/GetInvolved.html Wed May 20 23:36:41 2009
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+ <title>klee - Get Involved</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Getting Involved with the klee Project</h1>
+
+<p>FIXME: Intro.</p>
+
+<h2>Mailing Lists</h2>
+
+<p>klee-dev</p>
+
+<p>klee-commits</p>
+
+<h2>Working with the Code</h2>
+
+<p>FIXME: Point at pertinent LLVM docs.</p>
+
+<p>FIXME: Point at doxygen.</p>
+
+</div>
+</body>
+</html>
Added: klee/trunk/www/GetStarted.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/GetStarted.html?rev=72205&view=auto
==============================================================================
--- klee/trunk/www/GetStarted.html (added)
+++ klee/trunk/www/GetStarted.html Wed May 20 23:36:41 2009
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+ <title>KLEE - Getting Started</title>
+ <link type="text/css" rel="stylesheet" href="menu.css" />
+ <link type="text/css" rel="stylesheet" href="content.css" />
+</head>
+<body>
+
+<!--#include virtual="menu.html.incl"-->
+
+<div id="content">
+
+<h1>Getting Started: Building and Running KLEE</h1>
+
+<!-- <p>FIXME: Intro and disclaimer.</p> -->
+
+<h2 id="build">Building KLEE and Working with the Code</h2>
+
+<p>If you would like to check out and build KLEE, the current procedure is as
+follows:</p>
+
+KLEE is built on LLVM; the first steps are to get a working LLVM
+installation. See <a href="http://llvm.org/docs/GettingStarted.html">Getting
+Started with the LLVM System</a> for more information.
+
+<ol>
+<li>Install llvm-gcc:</li>
+<ul>
+<li>Download and install the LLVM 2.5 release of <tt>llvm-gcc</tt>
+ from <a href="http://llvm.org/releases/download.html">here</a>. It
+ is important to do this first so that it is found in
+ subsequent <tt>configure</tt> steps. <tt>llvm-gcc</tt> will be used
+ later to compile programs that KLEE can execute.</li>
+</ul>
+
+<li><a href="http://www.llvm.org/docs/GettingStarted.html#checkout">Checkout
+ and build LLVM</a> from SVN head:
+
+ <code class="instr"> <code>
+ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
+ cd llvm
+ ./configure --enable-optimized
+ make
+ </code></code>
+
+(the <tt>--enable-optimized</tt> configure argument is not
+necessary, but KLEE runs very slowly in Debug mode).
+ </li>
+
+ <li>Checkout KLEE (to any path you like):
+ <div class="instr">
+ svn co http://llvm.org/svn/llvm-project/klee/trunk klee
+ </div>
+ </li>
+
+ <li>Configure KLEE (from the KLEE source directory):
+ <div class="instr">
+ ./configure --with-llvm=<i>path/to/llvm</i>
+ </div>
+
+ <p>This assumes that you compiled LLVM in-place. If you used a
+ different directory for the object files then use:
+ <div class="instr">
+ ./configure --with-llvmsrc=<i>path/to/llvm/src</i>--with-llvmobj=<i>path/to/llvm/obj</i>
+ </div>
+ </li>
+
+ <li>Build KLEE (from the KLEE source directory):
+ <div class="instr">
+ make
+ </div>
+ </li>
+
+ <li>Run DejaGNU and unit tests to verify your build:
+ <div class="instr">
+ make check<br>
+ make unittests<br>
+ </div>
+ </li>
+
+ <li>You're ready to go! Go to the <a href="tutorials.html">Tutorials</a> page
+ to try KLEE.</li>
+</ol>
+
+<!-- <h2> Full Installation </h2> -->
+
+<!-- If you need uCLibc and/or POSIX support add <i>-with-uclibc</i> -->
+<!-- and <i>-enable-posix-runtime</i> to configure. Thus, to enable -->
+<!-- both, replace step 3 above with: -->
+
+<!-- <div class="instr"> -->
+<!-- ./configure -with-llvm=<i>path/to/llvm</i> -with-uclibc -enable-posix-runtime ENABLE_OPTIMIZED=1 -->
+<!-- </div> -->
+<!-- However, note that... -->
+
+</div>
+</body>
+</html>
Modified: klee/trunk/www/bugs.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/bugs.html?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/www/bugs.html (original)
+++ klee/trunk/www/bugs.html Wed May 20 23:36:41 2009
@@ -9,7 +9,7 @@
<link type="text/css" rel="stylesheet" href="content.css">
</head>
<body>
-<include virtual="menu.html.incl">
+<!--#include virtual="menu.html.incl"-->
<div id="content">
<!--*********************************************************************-->
<h1>KLEE Bug Reports</h1>
Modified: klee/trunk/www/content.css
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/content.css?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/www/content.css (original)
+++ klee/trunk/www/content.css Wed May 20 23:36:41 2009
@@ -1,6 +1,8 @@
html, body {
padding:0px;
- font-size:small; font-family:"Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, Helvetica, sans-serif; background-color: #fff; color: #222;
+ font-size:small;
+ font-family:"Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, Helvetica, sans-serif;
+ background-color: #fff; color: #222;
line-height:1.5;
}
@@ -24,11 +26,23 @@
/* Tables */
tr { vertical-align:top }
-/* Code */
-div.code{
+/* Instructions */
+div.instr{
border: 1px solid LightSteelBlue ;
font-family: Courier New;
background-color: #E3E3E3;
padding: 7px;
margin: 7px;
}
+
+/* Code */
+pre.code{
+ display:table;
+ text-align: left;
+ border: 1px solid LightSteelBlue ;
+ font-family: Courier New;
+ background-color: #E3E3E3;
+ margin: 10px;
+ padding: 10px;
+}
+
Modified: klee/trunk/www/index.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/index.html?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/www/index.html (original)
+++ klee/trunk/www/index.html Wed May 20 23:36:41 2009
@@ -27,7 +27,9 @@
the <a href="http://llvm.org/pubs/2008-12-OSDI-KLEE.html">OSDI
2008</a> paper.</p>
+<!-- <p>FIXME: Somewhere need to describe what KLEE can do well and what
+ is more "experimental" or research level. This should also address
+ how KLEE could be used by outside groups (i.e. kleaver).</p> -->
</div>
-
</body>
</html>
Modified: klee/trunk/www/install.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/install.html?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/www/install.html (original)
+++ klee/trunk/www/install.html Wed May 20 23:36:41 2009
@@ -9,7 +9,7 @@
<link type="text/css" rel="stylesheet" href="content.css">
</head>
<body>
-<include virtual="menu.html.incl">
+<!--#include virtual="menu.html.incl"-->
<div id="content">
<!--*********************************************************************-->
<h1>KLEE Installation Guide</h1>
Modified: klee/trunk/www/menu.html.incl
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/menu.html.incl?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/www/menu.html.incl (original)
+++ klee/trunk/www/menu.html.incl Wed May 20 23:36:41 2009
@@ -6,7 +6,10 @@
<div class="submenu">
<label>klee Info</label>
<a href="index.html">About</a>
- <a href="install.html">Download & Install</a>
+ <a href="GetStarted.html">Get Started</a>
+ <a href="GetInvolved.html">Get Involved</a>
+ <a href="tutorials.html">Tutorials</a>
+ <a href="Examples.html">Examples</a>
</div>
<div class="submenu">
@@ -14,5 +17,7 @@
<a href="http://keeda.stanford.edu/mailman/listinfo/klee-dev">klee-dev</a>
<a href="http://llvm.org/svn/llvm-project/klee/trunk/">Browse SVN</a>
<a href="http://llvm.org/viewvc/llvm-project/klee/trunk/">Browse ViewVC</a>
+ <a href="http://t1.minormatter.com/~ddunbar/klee-doxygen/index.html">doxygen</a>
+ <a href="http://t1.minormatter.com/~ddunbar/klee-cov/index.html">Testing Coverage</a>
</div>
</div>
Modified: klee/trunk/www/tutorials.html
URL: http://llvm.org/viewvc/llvm-project/klee/trunk/www/tutorials.html?rev=72205&r1=72204&r2=72205&view=diff
==============================================================================
--- klee/trunk/www/tutorials.html (original)
+++ klee/trunk/www/tutorials.html Wed May 20 23:36:41 2009
@@ -4,12 +4,12 @@
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
- <title>The klee Symbolic Virtual Machine</title>
+ <title>The KLEE Symbolic Virtual Machine</title>
<link type="text/css" rel="stylesheet" href="menu.css">
<link type="text/css" rel="stylesheet" href="content.css">
</head>
<body>
-<include virtual="menu.html.incl">
+<!--#include virtual="menu.html.incl"-->
<div id="content">
<!--*********************************************************************-->
<h1>KLEE Tutorials</h1>
More information about the llvm-commits
mailing list