8 # include <ctype.h> /* for isdigit */
9 # include "lclintMacros.nf"
11 # include "cgrammar.h"
12 # include "cgrammar_tokens.h"
14 # include "exprChecks.h"
15 # include "aliasChecks.h"
16 # include "exprNodeSList.h"
17 //# include "exprData.i"
19 #include "constraintExpr.h"
25 constraintList reflectChanges (constraintList pre2, constraintList post1);
26 constraint substitute (constraint c, constraintList p);
27 constraint constraint_searchandreplace (constraint c, constraintExpr old, constraintExpr new);
28 bool rangeCheck (arithType ar1, constraintExpr expr1, arithType ar2, constraintExpr expr2);
29 bool satifies (constraint pre, constraint post);
30 bool resolve (constraint c, constraintList p);
31 constraintList reflectChangesEnsures (constraintList pre2, constraintList post1);
32 constraint constraint_simplify (constraint c);
34 constraintList constraintList_fixConflicts (constraintList list1, constraintList list2);
36 constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2);
38 constraintList constraintList_mergeEnsures (constraintList list1, constraintList list2);
39 constraint inequalitySubstitute (constraint c, constraintList p);
41 /*********************************************/
44 constraintList constraintList_mergeEnsures (constraintList list1, constraintList list2)
48 ret = constraintList_new();
50 ret = reflectChangesEnsures (list1, list2);
51 ret = constraintList_fixConflicts (ret, list2);
52 ret = constraintList_subsumeEnsures (ret, list2);
53 list2 = constraintList_subsumeEnsures (list2, ret);
54 temp = constraintList_copy(list2);
56 temp = constraintList_addList (temp, ret);
58 //ret = constraintList_addList (ret, list2);
63 /* constraintList constraintList_resolveRequires (constraintList requires, constraintList ensures) */
66 /* constraintList ret; */
67 /* constraintList temp; */
68 /* ret = constraintList_new(); */
70 /* ret = reflectChangesEnsures (list1, list2); */
71 /* ret = constraintList_fixConflicts (ret, list2); */
72 /* ret = constraintList_subsumeEnsures (ret, list2); */
73 /* list2 = constraintList_subsumeEnsures (list2, ret); */
74 /* temp = constraintList_copy(list2); */
76 /* temp = constraintList_addList (temp, ret); */
78 /* //ret = constraintList_addList (ret, list2); */
82 void checkArgumentList (exprNode temp, exprNodeList arglist, fileloc sequencePoint)
84 temp->requiresConstraints = constraintList_new();
85 temp->ensuresConstraints = constraintList_new();
86 temp->trueEnsuresConstraints = constraintList_new();
87 temp->falseEnsuresConstraints = constraintList_new();
89 exprNodeList_elements (arglist, el)
91 exprNode_exprTraverse (el, FALSE, FALSE, sequencePoint);
92 el->requiresConstraints = exprNode_traversRequiresConstraints(el);
93 el->ensuresConstraints = exprNode_traversEnsuresConstraints(el);
95 temp->requiresConstraints = constraintList_addList(temp->requiresConstraints,
96 el->requiresConstraints);
98 temp->ensuresConstraints = constraintList_addList(temp->ensuresConstraints,
99 el->ensuresConstraints);
101 end_exprNodeList_elements;
105 constraintList checkCall (exprNode fcn, exprNodeList arglist)
107 constraintList preconditions;
109 DPRINTF ( (message ("Got call that %s ( %s) ", exprNode_unparse(fcn), exprNodeList_unparse (arglist ) ) ) );
111 temp = exprNode_getUentry (fcn);
113 preconditions = uentry_getFcnPreconditions (temp);
117 preconditions = constraintList_copy(preconditions);
118 preconditions= constraintList_togglePost (preconditions);
119 preconditions = constraintList_doSRefFixConstraintParam (preconditions, arglist);
123 preconditions = constraintList_new();
126 return preconditions;
129 constraintList getPostConditions (exprNode fcn, exprNodeList arglist, exprNode fcnCall)
131 constraintList postconditions;
133 DPRINTF ( (message ("Got call that %s ( %s) ", exprNode_unparse(fcn), exprNodeList_unparse (arglist ) ) ) );
135 temp = exprNode_getUentry (fcn);
137 postconditions = uentry_getFcnPostconditions (temp);
141 postconditions = constraintList_copy(postconditions);
142 postconditions = constraintList_doFixResult (postconditions, fcnCall);
143 postconditions = constraintList_doSRefFixConstraintParam (postconditions, arglist);
147 postconditions = constraintList_new();
150 return postconditions;
153 void mergeResolve (exprNode parent, exprNode child1, exprNode child2)
157 DPRINTF( (message ("magically merging constraint into parent:%s for", exprNode_unparse (parent) )));
159 DPRINTF( (message (" children: %s and %s", exprNode_unparse (child1), exprNode_unparse(child2) ) ) );
161 if (exprNode_isError (child1) || exprNode_isError(child2) )
163 if (exprNode_isError (child1) && !exprNode_isError(child2) )
165 parent->requiresConstraints = constraintList_copy (child2->requiresConstraints);
166 parent->ensuresConstraints = constraintList_copy (child2->ensuresConstraints);
167 DPRINTF((message ("Copied child constraints: pre: %s and post: %s",
168 constraintList_print( child2->requiresConstraints),
169 constraintList_print (child2->ensuresConstraints)
176 llassert(exprNode_isError(child2) );
177 parent->requiresConstraints = constraintList_new();
178 parent->ensuresConstraints = constraintList_new();
183 llassert(!exprNode_isError (child1) && ! exprNode_isError(child2) );
185 DPRINTF( (message ("Child constraints are %s %s and %s %s",
186 constraintList_print (child1->requiresConstraints),
187 constraintList_print (child1->ensuresConstraints),
188 constraintList_print (child2->requiresConstraints),
189 constraintList_print (child2->ensuresConstraints)
192 parent->requiresConstraints = constraintList_new();
193 parent->ensuresConstraints = constraintList_new();
195 parent->requiresConstraints = constraintList_copy (child1->requiresConstraints);
197 temp = reflectChanges (child2->requiresConstraints, child1->ensuresConstraints);
198 parent->requiresConstraints = constraintList_addList (parent->requiresConstraints, temp);
200 parent->ensuresConstraints = constraintList_mergeEnsures(child1->ensuresConstraints,
201 child2->ensuresConstraints);
203 DPRINTF( (message ("Parent constraints are %s and %s ",
204 constraintList_print (parent->requiresConstraints),
205 constraintList_print (parent->ensuresConstraints)
213 constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2)
216 ret = constraintList_new();
217 constraintList_elements (list1, el)
220 DPRINTF ((message ("Examining %s", constraint_print (el) ) ) );
221 if (!resolve (el, list2) )
223 ret = constraintList_add (ret, el);
227 DPRINTF ( (message ("Subsuming %s", constraint_print (el) ) ) );
229 } end_constraintList_elements;
235 constraintList reflectChanges (constraintList pre2, constraintList post1)
240 ret = constraintList_new();
241 DPRINTF((message ("reflectChanges: lists %s and %s", constraintList_print(pre2), constraintList_print(post1) )));
243 constraintList_elements (pre2, el)
245 if (!resolve (el, post1) )
247 temp = substitute (el, post1);
248 if (!resolve (temp, post1) )
250 // try inequality substitution
253 // the inequality substitution may cause us to lose information
254 //so we don't want to store the result but we do it anyway
255 temp2 = constraint_copy (temp);
256 temp2 = inequalitySubstitute (temp, post1);
257 if (!resolve (temp2, post1) )
258 ret = constraintList_add (ret, temp2);
261 } end_constraintList_elements;
263 DPRINTF((message ("reflectChanges: returning %s", constraintList_print(ret) ) ) );
269 constraintList reflectChangesEnsures (constraintList pre2, constraintList post1)
273 ret = constraintList_new();
274 constraintList_elements (pre2, el)
276 if (!resolve (el, post1) )
278 temp = substitute (el, post1);
279 llassert (temp != NULL);
281 if (!resolve (temp, post1) )
282 ret = constraintList_add (ret, temp);
286 DPRINTF ( (message ("Resolved away %s ", constraint_print(el) ) ) );
288 } end_constraintList_elements;
294 bool constraint_conflict (constraint c1, constraint c2)
297 if (constraintExpr_similar(c1->lexpr, c2->lexpr) )
300 if (c1->ar == c2->ar)
302 DPRINTF ( (message ("%s conflicts with %s ", constraint_print (c1), constraint_print(c2) ) ) );
307 DPRINTF ( (message ("%s doesn't conflict with %s ", constraint_print (c1), constraint_print(c2) ) ) );
313 void constraint_fixConflict (constraint good, constraint conflicting)
316 if (conflicting->ar ==EQ )
318 good->expr = constraintExpr_searchandreplace (good->expr, conflicting->lexpr, conflicting->expr);
319 temp = constraint_simplify (good);
320 constraint_overWrite (good, temp);
326 bool conflict (constraint c, constraintList list)
329 constraintList_elements (list, el)
331 if ( constraint_conflict(el, c) )
333 constraint_fixConflict (el, c);
336 } end_constraintList_elements;
343 //check if constraint in list1 and conflict with constraints in List2. If so we
344 //remove form list1 and (optionally) change list2.
345 constraintList constraintList_fixConflicts (constraintList list1, constraintList list2)
348 ret = constraintList_new();
349 constraintList_elements (list1, el)
351 if (! conflict (el, list2) )
353 ret = constraintList_add (ret, el);
355 } end_constraintList_elements;
362 bool resolve (constraint c, constraintList p)
364 constraintList_elements (p, el)
366 if ( satifies (c, el) )
368 DPRINTF ( (message ("\n%s Satifies %s\n ", constraint_print(el), constraint_print(c) ) ) );
371 DPRINTF ( (message ("\n%s does not satify %s\n ", constraint_print(el), constraint_print(c) ) ) );
373 end_constraintList_elements;
374 DPRINTF ( (message ("no constraints satify %s", constraint_print(c) ) ));
379 /*returns true if cosntraint post satifies cosntriant pre */
380 bool satifies (constraint pre, constraint post)
382 if (constraint_isAlwaysTrue (pre) )
385 if (!constraintExpr_similar (pre->lexpr, post->lexpr) )
389 if (post->expr == NULL)
395 return rangeCheck (pre->ar, pre->expr, post->ar, post->expr);
398 bool arithType_canResolve (arithType ar1, arithType ar2)
404 if ( (ar2 == GT) || (ar2 == GTE) || (ar2 == EQ) )
418 if ( (ar2 == LT) || (ar2 == LTE) || (ar2 == EQ) )
426 bool constraint_isAlwaysTrue (constraint c)
429 bool lHasConstant, rHasConstant;
430 int lConstant, rConstant;
435 if (constraintExpr_canGetValue(l) && constraintExpr_canGetValue(r) )
438 cmp = constraintExpr_compare (l, r);
458 if (constraintExpr_similar (l,r) )
476 l = constraintExpr_copy (c->lexpr);
477 r = constraintExpr_copy (c->expr);
479 // l = constraintExpr_propagateConstants (l, &lHasConstant, &lConstant);
480 r = constraintExpr_propagateConstants (r, &rHasConstant, &rConstant);
482 if (constraintExpr_similar (l,r) )
484 DPRINTF(( message("constraint_IsAlwaysTrue: after removing constants %s and %s are similar", constraintExpr_unparse(l), constraintExpr_unparse(r) ) ));
487 DPRINTF(( message("constraint_IsAlwaysTrue: rconstant is %d", rConstant ) ));
491 return (rConstant == 0);
493 return (rConstant > 0);
495 return (rConstant >= 0);
497 return (rConstant <= 0);
499 return (rConstant < 0);
510 DPRINTF(( message("Constraint %s is not always true", constraint_print(c) ) ));
517 bool rangeCheck (arithType ar1, constraintExpr expr1, arithType ar2, constraintExpr expr2)
520 DPRINTF ((message ("Doing Range CHECK %s and %s", constraintExpr_unparse(expr1), constraintExpr_unparse(expr2) ) ));
522 if (! arithType_canResolve (ar1, ar2) )
528 if (constraintExpr_similar (expr1, expr2) )
531 if (! (constraintExpr_canGetValue (expr1) &&
532 constraintExpr_canGetValue (expr2) ) )
534 DPRINTF( ("Can't Get value"));
538 if (constraintExpr_compare (expr2, expr1) >= 0)
543 if (constraintExpr_similar (expr1, expr2) )
548 if (constraintExpr_similar (expr1, expr2) )
551 if (! (constraintExpr_canGetValue (expr1) &&
552 constraintExpr_canGetValue (expr2) ) )
554 DPRINTF( ("Can't Get value"));
558 if (constraintExpr_compare (expr2, expr1) <= 0)
564 llcontbug((message("Unhandled case in switch: %s", arithType_print(ar1) ) ) );
571 constraint constraint_searchandreplace (constraint c, constraintExpr old, constraintExpr new)
573 DPRINTF (("Doing replace for lexpr") );
574 c->lexpr = constraintExpr_searchandreplace (c->lexpr, old, new);
575 DPRINTF (("Doing replace for expr") );
576 c->expr = constraintExpr_searchandreplace (c->expr, old, new);
580 bool constraint_search (constraint c, constraintExpr old)
585 ret = constraintExpr_search (c->lexpr, old);
586 ret = ret || constraintExpr_search (c->expr, old);
590 //adjust file locs and stuff
591 constraint constraint_adjust (constraint substitute, constraint old)
593 fileloc loc1, loc2, loc3;
595 DPRINTF ( (message("Start adjust on %s and %s", constraint_print(substitute),
596 constraint_print(old))
599 loc1 = constraint_getFileloc (old);
601 loc2 = constraintExpr_getFileloc (substitute->lexpr);
603 loc3 = constraintExpr_getFileloc (substitute->expr);
606 // special case of an equality that "contains itself"
607 if (constraintExpr_search (substitute->expr, substitute->lexpr) )
608 if (fileloc_closer (loc1, loc3, loc2))
611 DPRINTF ( (message("Doing adjust on %s", constraint_print(substitute) )
613 temp = substitute->lexpr;
614 substitute->lexpr = substitute->expr;
615 substitute->expr = temp;
616 substitute = constraint_simplify(substitute);
623 constraint inequalitySubstitute (constraint c, constraintList p)
628 constraintList_elements (p, el)
631 // if (!constraint_conflict (c, el) )
634 temp = constraint_copy(el);
636 // temp = constraint_adjust(temp, c);
638 if (constraintExpr_same (el->lexpr, c->expr) )
640 DPRINTF((message ("Replacing %s in %s with %s",
641 constraintExpr_print (c->expr),
642 constraint_print (c),
643 constraintExpr_print (el->expr) )
645 c->expr = constraintExpr_copy (el->expr);
650 end_constraintList_elements;
652 c = constraint_simplify(c);
656 constraint substitute (constraint c, constraintList p)
658 constraintList_elements (p, el)
661 if (!constraint_conflict (c, el) )
665 temp = constraint_copy(el);
667 temp = constraint_adjust(temp, c);
669 DPRINTF((message ("Substituting %s for %s",
670 constraint_print (temp), constraint_print (c)
674 c = constraint_searchandreplace (c, temp->lexpr, temp->expr);
677 end_constraintList_elements;
679 c = constraint_simplify(c);
684 constraint constraint_solve (constraint c)
686 DPRINTF( (message ("Solving %s\n", constraint_print(c) ) ) );
687 c->expr = constraintExpr_solveBinaryExpr (c->lexpr, c->expr);
688 DPRINTF( (message ("Solved and got %s\n", constraint_print(c) ) ) );
693 static arithType flipAr (arithType ar)
708 llcontbug (("unexpected value: case not handled"));
713 static constraint constraint_swapLeftRight (constraint c)
716 c->ar = flipAr (c->ar);
720 DPRINTF(("Swaped left and right sides of constraint"));
724 constraint constraint_simplify (constraint c)
726 c->lexpr = constraintExpr_simplify (c->lexpr);
727 c->expr = constraintExpr_simplify (c->expr);
729 c = constraint_solve (c);
731 c->lexpr = constraintExpr_simplify (c->lexpr);
732 c->expr = constraintExpr_simplify (c->expr);
734 if (constraintExpr_isLit(c->lexpr) && (!constraintExpr_isLit(c->expr) ) )
736 c = constraint_swapLeftRight(c);
737 /*I don't think this will be an infinate loop*/
738 constraint_simplify(c);
746 /* returns true if fileloc for term1 is closer to file for term2 than term3*/
748 bool fileloc_closer (fileloc loc1, fileloc loc2, fileloc loc3)
750 if ( fileloc_lessthan (loc1, loc2) )
752 if (fileloc_lessthan (loc2, loc3) )
754 llassert (fileloc_lessthan (loc1, loc3) );
763 if ( !fileloc_lessthan (loc1, loc2) )
765 if (!fileloc_lessthan (loc2, loc3) )
767 llassert (!fileloc_lessthan (loc1, loc3) );