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); */
83 constraintList checkCall (exprNode fcn, exprNodeList arglist)
85 constraintList preconditions;
87 DPRINTF ( (message ("Got call that %s ( %s) ", exprNode_unparse(fcn), exprNodeList_unparse (arglist ) ) ) );
89 temp = exprNode_getUentry (fcn);
91 preconditions = uentry_getFcnPreconditions (temp);
95 preconditions = constraintList_copy(preconditions);
96 preconditions= constraintList_togglePost (preconditions);
97 preconditions = constraintList_doSRefFixConstraintParam (preconditions, arglist);
101 preconditions = constraintList_new();
104 return preconditions;
107 constraintList getPostConditions (exprNode fcn, exprNodeList arglist, exprNode fcnCall)
109 constraintList postconditions;
111 DPRINTF ( (message ("Got call that %s ( %s) ", exprNode_unparse(fcn), exprNodeList_unparse (arglist ) ) ) );
113 temp = exprNode_getUentry (fcn);
115 postconditions = uentry_getFcnPostconditions (temp);
119 postconditions = constraintList_copy(postconditions);
120 postconditions = constraintList_doFixResult (postconditions, fcnCall);
121 postconditions = constraintList_doSRefFixConstraintParam (postconditions, arglist);
125 postconditions = constraintList_new();
128 return postconditions;
131 void mergeResolve (exprNode parent, exprNode child1, exprNode child2)
135 DPRINTF( (message ("magically merging constraint into parent:%s for", exprNode_unparse (parent) )));
137 DPRINTF( (message (" children: %s and %s", exprNode_unparse (child1), exprNode_unparse(child2) ) ) );
139 if (exprNode_isError (child1) || exprNode_isError(child2) )
141 if (exprNode_isError (child1) && !exprNode_isError(child2) )
143 parent->requiresConstraints = constraintList_copy (child2->requiresConstraints);
144 parent->ensuresConstraints = constraintList_copy (child2->ensuresConstraints);
145 DPRINTF((message ("Copied child constraints: pre: %s and post: %s",
146 constraintList_print( child2->requiresConstraints),
147 constraintList_print (child2->ensuresConstraints)
154 llassert(exprNode_isError(child2) );
155 parent->requiresConstraints = constraintList_new();
156 parent->ensuresConstraints = constraintList_new();
161 llassert(!exprNode_isError (child1) && ! exprNode_isError(child2) );
163 DPRINTF( (message ("Child constraints are %s %s and %s %s",
164 constraintList_print (child1->requiresConstraints),
165 constraintList_print (child1->ensuresConstraints),
166 constraintList_print (child2->requiresConstraints),
167 constraintList_print (child2->ensuresConstraints)
170 parent->requiresConstraints = constraintList_new();
171 parent->ensuresConstraints = constraintList_new();
173 parent->requiresConstraints = constraintList_copy (child1->requiresConstraints);
175 temp = reflectChanges (child2->requiresConstraints, child1->ensuresConstraints);
176 parent->requiresConstraints = constraintList_addList (parent->requiresConstraints, temp);
178 parent->ensuresConstraints = constraintList_mergeEnsures(child1->ensuresConstraints,
179 child2->ensuresConstraints);
181 DPRINTF( (message ("Parent constraints are %s and %s ",
182 constraintList_print (parent->requiresConstraints),
183 constraintList_print (parent->ensuresConstraints)
191 constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2)
194 ret = constraintList_new();
195 constraintList_elements (list1, el)
198 DPRINTF ((message ("Examining %s", constraint_print (el) ) ) );
199 if (!resolve (el, list2) )
201 ret = constraintList_add (ret, el);
205 DPRINTF ( (message ("Subsuming %s", constraint_print (el) ) ) );
207 } end_constraintList_elements;
213 constraintList reflectChanges (constraintList pre2, constraintList post1)
218 ret = constraintList_new();
219 DPRINTF((message ("reflectChanges: lists %s and %s", constraintList_print(pre2), constraintList_print(post1) )));
221 constraintList_elements (pre2, el)
223 if (!resolve (el, post1) )
225 temp = substitute (el, post1);
226 if (!resolve (temp, post1) )
228 // try inequality substitution
231 // the inequality substitution may cause us to lose information
232 //so we don't want to store the result but we do it anyway
233 temp2 = constraint_copy (temp);
234 temp2 = inequalitySubstitute (temp, post1);
235 if (!resolve (temp2, post1) )
236 ret = constraintList_add (ret, temp2);
239 } end_constraintList_elements;
241 DPRINTF((message ("reflectChanges: returning %s", constraintList_print(ret) ) ) );
247 constraintList reflectChangesEnsures (constraintList pre2, constraintList post1)
251 ret = constraintList_new();
252 constraintList_elements (pre2, el)
254 if (!resolve (el, post1) )
256 temp = substitute (el, post1);
257 llassert (temp != NULL);
259 if (!resolve (temp, post1) )
260 ret = constraintList_add (ret, temp);
264 DPRINTF ( (message ("Resolved away %s ", constraint_print(el) ) ) );
266 } end_constraintList_elements;
272 bool constraint_conflict (constraint c1, constraint c2)
275 if (constraintExpr_similar(c1->lexpr, c2->lexpr) )
278 if (c1->ar == c2->ar)
280 DPRINTF ( (message ("%s conflicts with %s ", constraint_print (c1), constraint_print(c2) ) ) );
285 DPRINTF ( (message ("%s doesn't conflict with %s ", constraint_print (c1), constraint_print(c2) ) ) );
291 void constraint_fixConflict (constraint good, constraint conflicting)
294 if (conflicting->ar ==EQ )
296 good->expr = constraintExpr_searchandreplace (good->expr, conflicting->lexpr, conflicting->expr);
297 temp = constraint_simplify (good);
298 constraint_overWrite (good, temp);
304 bool conflict (constraint c, constraintList list)
307 constraintList_elements (list, el)
309 if ( constraint_conflict(el, c) )
311 constraint_fixConflict (el, c);
314 } end_constraintList_elements;
321 //check if constraint in list1 and conflict with constraints in List2. If so we
322 //remove form list1 and (optionally) change list2.
323 constraintList constraintList_fixConflicts (constraintList list1, constraintList list2)
326 ret = constraintList_new();
327 constraintList_elements (list1, el)
329 if (! conflict (el, list2) )
331 ret = constraintList_add (ret, el);
333 } end_constraintList_elements;
340 bool resolve (constraint c, constraintList p)
342 constraintList_elements (p, el)
344 if ( satifies (c, el) )
346 DPRINTF ( (message ("\n%s Satifies %s\n ", constraint_print(el), constraint_print(c) ) ) );
349 DPRINTF ( (message ("\n%s does not satify %s\n ", constraint_print(el), constraint_print(c) ) ) );
351 end_constraintList_elements;
352 DPRINTF ( (message ("no constraints satify %s", constraint_print(c) ) ));
357 /*returns true if cosntraint post satifies cosntriant pre */
358 bool satifies (constraint pre, constraint post)
360 if (constraint_isAlwaysTrue (pre) )
363 if (!constraintExpr_similar (pre->lexpr, post->lexpr) )
367 if (post->expr == NULL)
373 return rangeCheck (pre->ar, pre->expr, post->ar, post->expr);
376 bool arithType_canResolve (arithType ar1, arithType ar2)
382 if ( (ar2 == GT) || (ar2 == GTE) || (ar2 == EQ) )
396 if ( (ar2 == LT) || (ar2 == LTE) || (ar2 == EQ) )
404 bool constraint_isAlwaysTrue (constraint c)
410 if (constraintExpr_canGetValue(l) && constraintExpr_canGetValue(r) )
413 cmp = constraintExpr_compare (l, r);
439 bool rangeCheck (arithType ar1, constraintExpr expr1, arithType ar2, constraintExpr expr2)
442 DPRINTF ((message ("Doing Range CHECK %s and %s", constraintExpr_unparse(expr1), constraintExpr_unparse(expr2) ) ));
444 if (! arithType_canResolve (ar1, ar2) )
450 if (constraintExpr_similar (expr1, expr2) )
453 if (! (constraintExpr_canGetValue (expr1) &&
454 constraintExpr_canGetValue (expr2) ) )
456 DPRINTF( ("Can't Get value"));
460 if (constraintExpr_compare (expr2, expr1) >= 0)
465 if (constraintExpr_similar (expr1, expr2) )
470 if (constraintExpr_similar (expr1, expr2) )
473 if (! (constraintExpr_canGetValue (expr1) &&
474 constraintExpr_canGetValue (expr2) ) )
476 DPRINTF( ("Can't Get value"));
480 if (constraintExpr_compare (expr2, expr1) <= 0)
486 llcontbug((message("Unhandled case in switch: %s", arithType_print(ar1) ) ) );
493 constraint constraint_searchandreplace (constraint c, constraintExpr old, constraintExpr new)
495 DPRINTF (("Doing replace for lexpr") );
496 c->lexpr = constraintExpr_searchandreplace (c->lexpr, old, new);
497 DPRINTF (("Doing replace for expr") );
498 c->expr = constraintExpr_searchandreplace (c->expr, old, new);
502 bool constraint_search (constraint c, constraintExpr old)
507 ret = constraintExpr_search (c->lexpr, old);
508 ret = ret || constraintExpr_search (c->expr, old);
512 //adjust file locs and stuff
513 constraint constraint_adjust (constraint substitute, constraint old)
515 fileloc loc1, loc2, loc3;
517 DPRINTF ( (message("Start adjust on %s and %s", constraint_print(substitute),
518 constraint_print(old))
521 loc1 = constraint_getFileloc (old);
523 loc2 = constraintExpr_getFileloc (substitute->lexpr);
525 loc3 = constraintExpr_getFileloc (substitute->expr);
528 // special case of an equality that "contains itself"
529 if (constraintExpr_search (substitute->expr, substitute->lexpr) )
530 if (fileloc_closer (loc1, loc3, loc2))
533 DPRINTF ( (message("Doing adjust on %s", constraint_print(substitute) )
535 temp = substitute->lexpr;
536 substitute->lexpr = substitute->expr;
537 substitute->expr = temp;
538 substitute = constraint_simplify(substitute);
545 constraint inequalitySubstitute (constraint c, constraintList p)
550 constraintList_elements (p, el)
553 // if (!constraint_conflict (c, el) )
556 temp = constraint_copy(el);
558 // temp = constraint_adjust(temp, c);
560 if (constraintExpr_same (el->lexpr, c->expr) )
562 DPRINTF((message ("Replacing %s in %s with %s",
563 constraintExpr_print (c->expr),
564 constraint_print (c),
565 constraintExpr_print (el->expr) )
567 c->expr = constraintExpr_copy (el->expr);
572 end_constraintList_elements;
574 c = constraint_simplify(c);
578 constraint substitute (constraint c, constraintList p)
580 constraintList_elements (p, el)
583 if (!constraint_conflict (c, el) )
587 temp = constraint_copy(el);
589 temp = constraint_adjust(temp, c);
591 DPRINTF((message ("Substituting %s for %s",
592 constraint_print (temp), constraint_print (c)
596 c = constraint_searchandreplace (c, temp->lexpr, temp->expr);
599 end_constraintList_elements;
601 c = constraint_simplify(c);
606 constraint constraint_solve (constraint c)
608 DPRINTF( (message ("Solving %s\n", constraint_print(c) ) ) );
609 c->expr = constraintExpr_solveBinaryExpr (c->lexpr, c->expr);
610 DPRINTF( (message ("Solved and got %s\n", constraint_print(c) ) ) );
615 static arithType flipAr (arithType ar)
630 llcontbug (("unexpected value: case not handled"));
635 static constraint constraint_swapLeftRight (constraint c)
638 c->ar = flipAr (c->ar);
642 DPRINTF(("Swaped left and right sides of constraint"));
646 constraint constraint_simplify (constraint c)
648 c->lexpr = constraintExpr_simplify (c->lexpr);
649 c->expr = constraintExpr_simplify (c->expr);
651 c = constraint_solve (c);
653 c->lexpr = constraintExpr_simplify (c->lexpr);
654 c->expr = constraintExpr_simplify (c->expr);
656 if (constraintExpr_isLit(c->lexpr) && (!constraintExpr_isLit(c->expr) ) )
658 c = constraint_swapLeftRight(c);
659 /*I don't think this will be an infinate loop*/
660 constraint_simplify(c);
668 /* returns true if fileloc for term1 is closer to file for term2 than term3*/
670 bool fileloc_closer (fileloc loc1, fileloc loc2, fileloc loc3)
672 if ( fileloc_lessthan (loc1, loc2) )
674 if (fileloc_lessthan (loc2, loc3) )
676 llassert (fileloc_lessthan (loc1, loc3) );
685 if ( !fileloc_lessthan (loc1, loc2) )
687 if (!fileloc_lessthan (loc2, loc3) )
689 llassert (!fileloc_lessthan (loc1, loc3) );