00001 package edu.ksu.cis.bandera.dspin;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import Bandera;
00036 import java.io.*;
00037 import java.util.Properties;
00038 import java.util.Vector;
00039 import java.util.StringTokenizer;
00040 import java.util.List;
00041 import java.util.LinkedList;
00042
00043 import edu.ksu.cis.bandera.bir.*;
00044 import edu.ksu.cis.bandera.spin.*;
00045 import edu.ksu.cis.bandera.checker.*;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 public class DSpinTrans extends AbstractExprSwitch implements BirConstants, Checker
00065 {
00066 TransSystem system;
00067 PrintWriter out;
00068 DSpinTypeName namer;
00069 int indentLevel = 0;
00070 boolean inDefine = false;
00071 boolean newLine = true;
00072 boolean resetTemp = false;
00073 boolean resetNew = false;
00074 Transformation currentTrans;
00075 int actionNum;
00076 DSpinOptions options;
00077 boolean ranVerifier = false;
00078
00079 static String ccName = "gcc";
00080 static String includeDir = "";
00081 static Runtime runtime = Runtime.getRuntime();
00082 public static final String normal = "NORMAL_CASE";
00083
00084 static final int BUFSIZE = 50000;
00085 static byte [] buffer = new byte[BUFSIZE];
00086
00087 static {
00088
00089
00090
00091 }
00092 DSpinTrans(TransSystem system, DSpinOptions options, PrintWriter out) {
00093 this.system = system;
00094 this.out = out;
00095 this.namer = new DSpinTypeName();
00096 this.options = (options == null) ? new DSpinOptions() : options;
00097 }
00098 String actionId() {
00099 int locNum = currentTrans.getFromLoc().getId();
00100 int transNum =
00101 currentTrans.getFromLoc().getOutTrans().indexOf(currentTrans);
00102 return locNum + " " + transNum + " " + actionNum;
00103 }
00104 String actionIdWithCommas() {
00105 int locNum = currentTrans.getFromLoc().getId();
00106 int transNum =
00107 currentTrans.getFromLoc().getOutTrans().indexOf(currentTrans);
00108 return locNum + "," + transNum + "," + actionNum;
00109 }
00110 CaseNode applyTo(Expr expr) {
00111 expr.apply(this);
00112 return (CaseNode) getResult();
00113 }
00114 public void caseAddExpr(AddExpr expr)
00115 {
00116 translateBinaryOp(expr.getOp1(), expr.getOp2(), " + ");
00117 }
00118 public void caseAndExpr(AndExpr expr)
00119 {
00120 translateBinaryOp(expr.getOp1(), expr.getOp2(), " && ");
00121 }
00122 public void caseArrayExpr(ArrayExpr expr)
00123 {
00124 String ref = "";
00125 if (expr.getType().isKind(REF))
00126 ref = ".ref";
00127 TreeNode arrayTree = applyTo(expr.getArray());
00128 TreeNode indexTree = applyTo(expr.getIndex());
00129 TreeNode result = arrayTree.compose(indexTree,null);
00130 Vector leafCases = result.getLeafCases(new Vector());
00131 for (int i = 0; i < leafCases.size(); i++) {
00132 Case leafCase = (Case) leafCases.elementAt(i);
00133 ExprNode leaf = (ExprNode) leafCase.node;
00134 leafCase.insertTrap(leaf.expr2 + " >= " + leaf.expr1 + ".length",
00135 "ArrayIndexOutOfBoundsException",true);
00136 leafCase.insertTrap(leaf.expr2 + " < 0",
00137 "ArrayIndexOutOfBoundsException",true);
00138 leaf.update(leaf.expr1 + ".elements[" + leaf.expr2 + "]" + ref);
00139 }
00140 setResult(result);
00141 }
00142 public void caseAssertAction(AssertAction assertAction) {
00143 CaseNode condTree = (CaseNode) applyTo(assertAction.getCondition());
00144 Vector leaves = condTree.getLeaves(new Vector());
00145 for (int i = 0; i < leaves.size(); i++) {
00146 ExprNode leaf = (ExprNode) leaves.elementAt(i);
00147 leaf.update("assert(" + leaf.expr1 + ");");
00148 }
00149 printStatement(condTree.getCase(normal));
00150 }
00151 public void caseAssignAction(AssignAction assign)
00152 {
00153 TreeNode rhsTree = applyTo(assign.getRhs());
00154 TreeNode lhsTree = applyTo(assign.getLhs());
00155 CaseNode result = (CaseNode) lhsTree.compose(rhsTree,null);
00156 Vector leafCases = result.getLeafCases(new Vector());
00157 for (int i = 0; i < leafCases.size(); i++) {
00158 Case leafCase = (Case) leafCases.elementAt(i);
00159 ExprNode leaf = (ExprNode) leafCase.node;
00160 Type rhsType = assign.getRhs().getType();
00161 Type lhsType = assign.getLhs().getType();
00162
00163 if (! rhsType.isSubtypeOf(lhsType)) {
00164
00165
00166 if (lhsType.isKind(RANGE)
00167 && ! lhsType.containsValue(assign.getRhs())) {
00168 Range range = (Range) lhsType;
00169 leafCase.insertTrap(leaf.expr2 + " < "
00170 + range.getFromVal(),
00171 "RangeLimitException", false);
00172 leafCase.insertTrap(leaf.expr2 + " > "
00173 + range.getToVal(),
00174 "RangeLimitException", false);
00175 }
00176
00177
00178 if (lhsType.isKind(REF)
00179 && ! (assign.getRhs() instanceof NullExpr)) {
00180 String trapDesc = "ClassCastException";
00181 StateVarVector lhsTargets = ((Ref)lhsType).getTargets();
00182 StateVarVector rhsTargets = ((Ref)rhsType).getTargets();
00183 for (int j = 0; j < rhsTargets.size(); j++)
00184 if (! lhsTargets.contains(rhsTargets.elementAt(j))) {
00185 String check = leaf.expr2 + ".refIndex == " +
00186 refIndex(rhsTargets.elementAt(j));
00187 leafCase.insertTrap(check,
00188 "ClassCastException",true);
00189 }
00190 }
00191 }
00192 leaf.update(leaf.expr1 + " = " + leaf.expr2 + ";");
00193 }
00194 printStatement(result.getCase(normal));
00195 }
00196 public void caseBoolLit(BoolLit expr)
00197 {
00198 setResult(specialize("" + expr.getValue()));
00199 }
00200 public void caseChooseExpr(ChooseExpr expr)
00201 {
00202 Vector choices = expr.getChoices();
00203 println("if");
00204 for (int i = 0; i < choices.size(); i++) {
00205 Expr choice = (Expr) choices.elementAt(i);
00206 ExprNode leaf = (ExprNode) applyTo(choice).getCase(normal);
00207 println(":: _temp_ = " + leaf.expr1 + "; printf(\"BIR? " +
00208 actionNum + " " + i + "\\n\"); ");
00209 }
00210 println("fi;");
00211 resetTemp = true;
00212 setResult(specialize("_temp_"));
00213 }
00214 public void caseConstant(Constant expr)
00215 {
00216 setResult(specialize(expr.getName()));
00217 }
00218 public void caseDerefExpr(DerefExpr expr)
00219 {
00220 TreeNode result = applyTo(expr.getTarget());
00221 StateVarVector targets =
00222 ((Ref)expr.getTarget().getType()).getTargets();
00223 Vector leafCases = result.getLeafCases(new Vector());
00224 for (int i = 0; i < leafCases.size(); i++) {
00225 Case leafCase = (Case) leafCases.elementAt(i);
00226 ExprNode leaf = (ExprNode) leafCase.node;
00227 CaseNode caseNode = new CaseNode();
00228 String cond = "(" + leaf.expr1 + " != null)";
00229 caseNode.addCase(cond, leaf.expr1);
00230 cond = "(" + leaf.expr1 + " == null)";
00231 caseNode.addTrapCase(cond,"NullPointerException", true);
00232 leafCase.replace(caseNode);
00233 }
00234 setResult(result);
00235 }
00236 public void caseDivExpr(DivExpr expr)
00237 {
00238 TreeNode e1Tree = applyTo(expr.getOp1());
00239 TreeNode e2Tree = applyTo(expr.getOp2());
00240 TreeNode result = e1Tree.compose(e2Tree,null);
00241 Vector leafCases = result.getLeafCases(new Vector());
00242 for (int i = 0; i < leafCases.size(); i++) {
00243 Case leafCase = (Case) leafCases.elementAt(i);
00244 ExprNode leaf = (ExprNode) leafCase.node;
00245 leafCase.insertTrap(leaf.expr2 + " == 0",
00246 "ArithmeticException",true);
00247 leaf.update("(" + leaf.expr1 + " / " + leaf.expr2 + ")");
00248 }
00249 setResult(result);
00250 }
00251 public void caseEqExpr(EqExpr expr)
00252 {
00253 translateBinaryOp(expr.getOp1(), expr.getOp2(), " == ");
00254 }
00255 public void caseInstanceOfExpr(InstanceOfExpr expr)
00256 {
00257 TreeNode result = applyTo(expr.getRefExpr());
00258 StateVarVector targets = expr.getRefType().getTargets();
00259 Vector leafCases = result.getLeafCases(new Vector());
00260 for (int i = 0; i < leafCases.size(); i++) {
00261 Case leafCase = (Case) leafCases.elementAt(i);
00262 ExprNode leaf = (ExprNode) leafCase.node;
00263 CaseNode caseNode = new CaseNode();
00264 String elseCond = "! (";
00265 for (int j = 0; j < targets.size(); j++) {
00266 StateVar target = targets.elementAt(j);
00267 String cond = "(" + leaf.expr1 + ".refIndex == "
00268 + refIndex(target) + ")";
00269 caseNode.addCase(cond,"1");
00270 if (j > 0) elseCond += " || ";
00271 elseCond += cond;
00272 }
00273 elseCond += ")";
00274 caseNode.addCase(elseCond,"0");
00275 leafCase.replace(caseNode);
00276 }
00277 setResult(result);
00278 }
00279 public void caseIntLit(IntLit expr)
00280 {
00281 setResult(specialize("" + expr.getValue()));
00282 }
00283 public void caseLeExpr(LeExpr expr)
00284 {
00285 translateBinaryOp(expr.getOp1(), expr.getOp2(), " <= ");
00286 }
00287 public void caseLengthExpr(LengthExpr expr)
00288 {
00289 TreeNode result = applyTo(expr.getArray());
00290 Vector leaves = result.getLeaves(new Vector());
00291 for (int i = 0; i < leaves.size(); i++) {
00292 ExprNode leaf = (ExprNode) leaves.elementAt(i);
00293 leaf.update(leaf.expr1 + ".length");
00294 }
00295 setResult(result);
00296 }
00297 public void caseLockAction(LockAction lockAction)
00298 {
00299 CaseNode lockTree = (CaseNode) applyTo(lockAction.getLockExpr());
00300 String opName = "_" +
00301 LockAction.operationName(lockAction.getOperation());
00302 if (lockAction.isWait())
00303 opName += "_" + lockAction.getThread().getId();
00304 Lock lockType = (Lock) lockAction.getLockExpr().getType();
00305 if (lockType.isReentrant()
00306 && ! lockAction.isLockAction(NOTIFY|NOTIFYALL))
00307 opName += "_R";
00308 Vector leaves = lockTree.getLeaves(new Vector());
00309 for (int i = 0; i < leaves.size(); i++) {
00310 ExprNode leaf = (ExprNode) leaves.elementAt(i);
00311 leaf.update(opName + "(" + leaf.expr1 + "," +
00312 actionIdWithCommas() + ");");
00313 }
00314 printStatement(lockTree.getCase(normal));
00315 }
00316 public void caseLockTest(LockTest lockTest) {
00317 TreeNode lockTree;
00318 Vector leaves;
00319 switch (lockTest.getOperation()) {
00320 case LOCK_AVAILABLE:
00321 String opName = "_lockAvailable";
00322 if (((Lock)lockTest.getLockExpr().getType()).isReentrant())
00323 opName += "_R";
00324 lockTree = applyTo(lockTest.getLockExpr());
00325 leaves = lockTree.getLeaves(new Vector());
00326 for (int i = 0; i < leaves.size(); i++) {
00327 ExprNode leaf = (ExprNode) leaves.elementAt(i);
00328 leaf.update(opName + "(" + leaf.expr1 + ")");
00329 }
00330 setResult(lockTree);
00331 return;
00332 case HAS_LOCK:
00333 setResult(specialize("true"));
00334 return;
00335 case WAS_NOTIFIED:
00336 lockTree = applyTo(lockTest.getLockExpr());
00337 leaves = lockTree.getLeaves(new Vector());
00338 for (int i = 0; i < leaves.size(); i++) {
00339 ExprNode leaf = (ExprNode) leaves.elementAt(i);
00340 leaf.update("_wasNotified_" + lockTest.getThread().getId()
00341 + "(" + leaf.expr1 + ")");
00342 }
00343 setResult(lockTree);
00344 return;
00345 }
00346 }
00347 public void caseLtExpr(LtExpr expr)
00348 {
00349 translateBinaryOp(expr.getOp1(), expr.getOp2(), " < ");
00350 }
00351 public void caseMulExpr(MulExpr expr)
00352 {
00353 translateBinaryOp(expr.getOp1(), expr.getOp2(), " * ");
00354 }
00355 public void caseNeExpr(NeExpr expr)
00356 {
00357 translateBinaryOp(expr.getOp1(), expr.getOp2(), " != ");
00358 }
00359 public void caseNewArrayExpr(NewArrayExpr expr)
00360 {
00361 Collection colType = (Collection)expr.getCollection().getType();
00362 Array arrayType = (Array)colType.getBaseType();
00363 String arrayTypeName = dSpinTypeName(arrayType,null);
00364 Type baseType = arrayType.getBaseType();
00365 String baseTypeName = dSpinTypeName(baseType,null);
00366 if (baseType.isKind(REF))
00367 baseTypeName = baseTypeName.substring(0,baseTypeName.length() - 4)
00368 + "_aref";
00369 int refIndex = refIndex(expr.getCollection());
00370 CaseNode setLength = applyTo(expr.getLength());
00371 Vector leafCases = setLength.getLeafCases(new Vector());
00372 for (int i = 0; i < leafCases.size(); i++) {
00373 Case leafCase = (Case) leafCases.elementAt(i);
00374 ExprNode leaf = (ExprNode) leafCase.node;
00375 leaf.update("_temp_ = " + leaf.expr1 + ";");
00376 }
00377 printStatement(setLength.getCase(normal));
00378 resetTemp = true;
00379 println("_new_ = new " + arrayTypeName + ";");
00380 println("_new_.refIndex = " + refIndex + ";");
00381 println("_new_.length = _temp_;");
00382 println("_new_.elements = new " + baseTypeName + "[_temp_];");
00383 println("printf(\"BIR? " + actionNum + " %d\\n\",_temp_); ");
00384 resetNew = true;
00385 setResult(specialize("_new_"));
00386 }
00387 public void caseNewExpr(NewExpr expr)
00388 {
00389 Type type = ((Collection)expr.getCollection().getType()).getBaseType();
00390 String typeName = dSpinTypeName(type,null);
00391 println("_new_ = new " + typeName + ";");
00392 println("_new_.refIndex = " + refIndex(expr.getCollection()) + ";");
00393 resetNew = true;
00394 setResult(specialize("_new_"));
00395 }
00396 public void caseNotExpr(NotExpr expr)
00397 {
00398 translateUnaryOp(expr.getOp(),"! ");
00399 }
00400 public void caseNullExpr(NullExpr expr)
00401 {
00402 setResult(specialize("null"));
00403 }
00404 public void caseOrExpr(OrExpr expr)
00405 {
00406 translateBinaryOp(expr.getOp1(), expr.getOp2(), " || ");
00407 }
00408 public void casePrintAction(PrintAction printAction) {
00409
00410 if (printAction.getPrintItems().size() > 0) {
00411 String format = "BIR|";
00412 String params = "";
00413 Vector printItems = printAction.getPrintItems();
00414 for (int i = 0; i < printItems.size(); i++) {
00415 Object item = printItems.elementAt(i);
00416 if (item instanceof String)
00417 format += item;
00418 else {
00419 format += "%d";
00420 CaseNode varTree = (CaseNode) applyTo((Expr)item);
00421 params += "," + ((ExprNode)varTree.getCase(normal)).expr1;
00422 }
00423 }
00424 println("printf(\"" + format + "\\n\"" + params + "); ");
00425 }
00426 }
00427 public void caseRecordExpr(RecordExpr expr)
00428 {
00429 TreeNode result = applyTo(expr.getRecord());
00430 String field = expr.getField().getName();
00431 Vector leaves = result.getLeaves(new Vector());
00432 for (int i = 0; i < leaves.size(); i++) {
00433 ExprNode leaf = (ExprNode) leaves.elementAt(i);
00434 leaf.update(leaf.expr1 + "." + field);
00435 }
00436 setResult(result);
00437 }
00438 public void caseRefExpr(RefExpr expr)
00439 {
00440 setResult(specialize("& " + expr.getTarget().getName()));
00441 }
00442 public void caseRemExpr(RemExpr expr)
00443 {
00444 TreeNode e1Tree = applyTo(expr.getOp1());
00445 TreeNode e2Tree = applyTo(expr.getOp2());
00446 TreeNode result = e1Tree.compose(e2Tree,null);
00447 Vector leafCases = result.getLeafCases(new Vector());
00448 for (int i = 0; i < leafCases.size(); i++) {
00449 Case leafCase = (Case) leafCases.elementAt(i);
00450 ExprNode leaf = (ExprNode) leafCase.node;
00451 leafCase.insertTrap(leaf.expr2 + " == 0",
00452 "ArithmeticException",true);
00453 leaf.update("(" + leaf.expr1 + " % " + leaf.expr2 + ")");
00454 }
00455 setResult(result);
00456 }
00457 public void caseStateVar(StateVar expr)
00458 {
00459 setResult(specialize(expr.getName()));
00460 }
00461 public void caseSubExpr(SubExpr expr)
00462 {
00463 translateBinaryOp(expr.getOp1(), expr.getOp2(), " - ");
00464 }
00465 public void caseThreadAction(ThreadAction threadAction)
00466 {
00467 String opName =
00468 ThreadAction.operationName(threadAction.getOperation());
00469 int threadId = threadAction.getThreadArg().getId();
00470 println("_" + opName + "Thread_" + threadId + ";");
00471 }
00472 public void caseThreadLocTest(ThreadLocTest threadLocTest) {
00473 String threadName = threadLocTest.getThread().getName();
00474 int threadId = 1 + threadLocTest.getThread().getId();
00475 String locLabel = locLabel(threadLocTest.getLocation());
00476 String test = threadName + "[" + threadId + "]@" + locLabel;
00477 setResult(specialize(test));
00478 }
00479 public void caseThreadTest(ThreadTest threadTest) {
00480 switch (threadTest.getOperation()) {
00481 case THREAD_TERMINATED:
00482 String opName =
00483 ThreadTest.operationName(threadTest.getOperation());
00484 int threadId = threadTest.getThreadArg().getId();
00485 String test = "_" + opName + "_" + threadId;
00486 setResult(specialize(test));
00487 return;
00488 }
00489 }
00490 public String check() { return runSpin(); }
00491 static String currentDir() { return System.getProperty("user.dir"); }
00492 public void defaultCase(Object obj)
00493 {
00494 throw new RuntimeException("Trans type not handled: " + obj);
00495 }
00496 void definitions() {
00497 Vector definitions = system.getDefinitions();
00498 for (int i = 0; i < definitions.size(); i++) {
00499 Definition def = (Definition) definitions.elementAt(i);
00500 if (def instanceof Constant)
00501 println("#define " + def.getName() + " " + def.getDef());
00502 }
00503 Vector types = system.getTypes();
00504 for (int i = 0; i < types.size(); i++) {
00505 Type type = (Type) types.elementAt(i);
00506 if (type.isKind(BOOL|RANGE|LOCK|ENUMERATED|REF)) {
00507 println("/* " + type.typeName() + " = " + type + " */");
00508 print("#define " + type.typeName() + " ");
00509 println(dSpinTypeName(type,this));
00510 if (type.isKind(ENUMERATED)) {
00511 Enumerated enum = (Enumerated) type;
00512 for (int j = 0; j < enum.getEnumeratedSize(); j++) {
00513 String name = enum.getNameOf(enum.getFirstElement()+j);
00514 if (name != null)
00515 println("#define " + name + " " +
00516 (enum.getFirstElement()+j));
00517 }
00518 }
00519 println();
00520 }
00521 if (type.isKind(RECORD|ARRAY)) {
00522 println("typedef " + type.typeName() + ";");
00523 println();
00524 }
00525 }
00526 for (int i = 0; i < types.size(); i++) {
00527 Type type = (Type) types.elementAt(i);
00528 if (type.isKind(REF)) {
00529 String refRoot =
00530 type.typeName().substring(0,type.typeName().length() - 4);
00531 println("typedef " + refRoot + "_aref { " +
00532 type.typeName() + " ref; }");
00533 println();
00534 }
00535 }
00536 for (int i = 0; i < types.size(); i++) {
00537 Type type = (Type) types.elementAt(i);
00538 if (! type.isKind(BOOL|RANGE|LOCK|ENUMERATED|REF|COLLECTION)) {
00539 println("/* " + type.typeName() + " = " + type + " */");
00540 print("typedef " + type.typeName() + " ");
00541 println(dSpinTypeName(type,this));
00542 println();
00543 }
00544 }
00545 println();
00546 }
00547 String dSpinTypeName(Type type, Object o) {
00548 type.apply(namer,o);
00549 return (String) namer.getResult();
00550 }
00551 String execAndWait(String command, boolean verbose) {
00552 try {
00553 if (verbose)
00554 System.out.println(command);
00555 Process p = runtime.exec(command);
00556 InputStream commandErr = p.getErrorStream();
00557 InputStream commandOut = p.getInputStream();
00558 int count = 0;
00559 int charsRead = 0;
00560 int charsAvail = 0;
00561 while ((count < BUFSIZE) && (charsRead >= 0)) {
00562 charsAvail = commandErr.available();
00563 if (charsAvail > 0)
00564 count += commandErr.read(buffer,count,charsAvail);
00565 charsRead = commandOut.read(buffer,count,BUFSIZE - count);
00566 if (charsRead > 0)
00567 count += charsRead;
00568 }
00569 p.waitFor();
00570 String output = new String(buffer,0,count);
00571 if (verbose && count > 0)
00572 System.out.println(output);
00573 return output;
00574 }
00575 catch (Exception e) {
00576 throw new RuntimeException("exec of command '" + command
00577 + "' was aborted: \n" + e);
00578 }
00579 }
00580
00581
00582
00583 public List getCounterExample() {
00584 return null;
00585 }
00586 public DSpinOptions getDSpinOptions() { return options; }
00587 String getSimpleResult() {
00588 TreeNode result = ((CaseNode)getResult()).getCase(normal);
00589 if (result instanceof ExprNode)
00590 return ((ExprNode)result).expr1;
00591 else
00592 throw new RuntimeException("Result not simple: " + result);
00593 }
00594 boolean guardPresent(Transformation trans) {
00595 Expr guard = trans.getGuard();
00596 if (guard == null)
00597 return false;
00598 if (guard instanceof BoolLit)
00599 return ! ((BoolLit)guard).getValue();
00600 if ((guard instanceof LockTest)
00601 && ((LockTest)guard).getOperation() == HAS_LOCK)
00602 return false;
00603 return true;
00604 }
00605 void header() {
00606 ThreadVector threadVector = system.getThreads();
00607
00608 println("/* (dSPIN) Promela for transition system: "
00609 + system.getName() + " */");
00610 println();
00611
00612
00613 println("/* Lock operations */");
00614 println("typedef lock_ {\n byte owner;\n};");
00615 println("typedef lock_W {\n byte owner;\n int waiting;\n};");
00616 println("typedef lock_R {\n byte count;\n byte owner;\n};");
00617 println("typedef lock_RW {\n byte count;\n byte owner;\n int waiting;\n};");
00618
00619
00620 println("#define _lock(sync,locNum,transNum,actionNum) \\");
00621 println(" sync.owner = _pid ");
00622 println("#define _lock_R(sync,locNum,transNum,actionNum) \\");
00623 println(" if \\");
00624 println(" :: sync.owner == _pid -> sync.count++; \\");
00625 println(" :: else -> sync.owner = _pid; \\");
00626 println(" fi ");
00627
00628 println("#define _unlock(sync,locNum,transNum,actionNum) \\");
00629 println(" sync.owner = 0 ");
00630 println("#define _unlock_R(sync,locNum,transNum,actionNum) \\");
00631 println(" if \\");
00632 println(" :: sync.count > 0 -> sync.count--; \\");
00633 println(" :: else -> sync.owner = 0; \\");
00634 println(" fi ");
00635
00636 println("#define _lockAvailable(sync) \\");
00637 println(" (sync.owner == 0)");
00638 println("#define _lockAvailable_R(sync) \\");
00639 println(" (sync.owner == 0 || sync.owner == _pid) ");
00640
00641 println("#define _unwait(sync,locNum,transNum,actionNum) \\");
00642 println(" sync.owner = _pid ");
00643 println("#define _unwait_R(sync,locNum,transNum,actionNum) \\");
00644 println(" sync.owner = _pid; sync.count = _temp_; _temp_ = 0 ");
00645
00646 println("#define _notifyAll(sync,locNum,transNum,actionNum) \\");
00647 println(" if \\");
00648 println(" :: sync.owner == _pid -> sync.waiting = 0; \\");
00649 println(" :: else -> printf(\"BIR: locNum transNum actionNum IllegalMonitorStateException\"); assert(0); \\");
00650 println(" fi ");
00651
00652 println("#define _notify(sync,locNum,transNum,actionNum) \\");
00653 println(" if \\");
00654 for (int i = 0; i < threadVector.size(); i++) {
00655 int thread = (1 << i);
00656 println(" :: (sync.owner == _pid) && (sync.waiting & " + thread + ") -> sync.waiting = sync.waiting & " + ~ thread + " ; printf(\"BIR? %d " + i + "\",actionNum); \\");
00657 }
00658 println(" :: (sync.owner == _pid) && (sync.waiting == 0) -> printf(\"BIR? %d " + threadVector.size() + "\\n\",actionNum); \\");
00659 println(" :: else -> printf(\"BIR: locNum transNum actionNum IllegalMonitorStateException\"); assert(0); \\");
00660 println(" fi ");
00661
00662 for (int i = 0; i < threadVector.size(); i++) {
00663 int thread = (1 << i);
00664
00665 println("#define _wait_" + i + "(sync,locNum,transNum,actionNum) \\");
00666 println(" if \\");
00667 println(" :: sync.owner == _pid -> sync.waiting = sync.waiting | " + thread + "; \\");
00668 println(" sync.owner = 0; \\");
00669 println(" :: else -> printf(\"BIR: locNum transNum actionNum IllegalMonitorStateException\"); assert(0); \\");
00670 println(" fi ");
00671 println("#define _wait_" + i + "_R(sync,locNum,transNum,actionNum) \\");
00672 println(" if \\");
00673 println(" :: sync.owner == _pid -> sync.waiting = sync.waiting | " + thread + "; \\");
00674 println(" _temp_ = sync.count; sync.count = 0; sync.owner = 0; \\");
00675 println(" :: else -> printf(\"BIR: locNum transNum actionNum IllegalMonitorStateException\"); assert(0); \\");
00676 println(" fi ");
00677
00678 println("#define _wasNotified_" + i + "(sync) \\");
00679 println(" !(sync.waiting & " + thread + ") ");
00680
00681 if (! threadVector.elementAt(i).isMain()) {
00682 println("#define _startThread_" + i + " \\");
00683 println(" _threadActive_" + i + " = 1; _threadStart_" +
00684 i + "!ready");
00685 println("#define _beginThread_" + i + " \\");
00686 println(" _threadStart_" + i + "?ready");
00687 println("#define _joinThread_" + i + " \\");
00688 println(" skip");
00689 println("#define _exitThread_" + i + " \\");
00690 println(" _threadActive_" + i + " = 0; goto endtop_" + i);
00691 println("#define _threadTerminated_" + i + " \\");
00692 println(" (_threadActive_" + i + " == 0)");
00693 }
00694 }
00695
00696 println("typedef object {\n byte refIndex;\n byte length; object& elements\n};");
00697 println("#define TRAP 1");
00698 println("mtype { ready };");
00699 println();
00700 }
00701 void initBlock() {
00702 ThreadVector threadVector = system.getThreads();
00703 println("init {");
00704 indentLevel = 2;
00705 println("atomic {");
00706 indentLevel++;
00707 StateVarVector stateVarVector = system.getStateVars();
00708 DSpinTypeInit initializer = new DSpinTypeInit(this,out);
00709 for (int i = 0; i < stateVarVector.size(); i++) {
00710 StateVar var = stateVarVector.elementAt(i);
00711 var.getType().apply(initializer,var);
00712 }
00713 for (int i = 0; i < threadVector.size(); i++) {
00714 BirThread thread = threadVector.elementAt(i);
00715 println("assert(run " + thread.getName() + "() == " +
00716 (1 + thread.getId()) + ");");
00717 }
00718 indentLevel--;
00719 println("}");
00720 println("assert(! limit_exception);");
00721 indentLevel = 0;
00722 println("}");
00723 }
00724 boolean isIfBranch(TransVector outTrans) {
00725 if (outTrans.size() != 2)
00726 return false;
00727 Expr guard1 = outTrans.elementAt(0).getGuard();
00728 Expr guard2 = outTrans.elementAt(1).getGuard();
00729 if (guard1 == null || guard2 == null)
00730 return false;
00731 if ((guard1 instanceof NotExpr)
00732 && ((NotExpr)guard1).getOp().equals(guard2))
00733 return true;
00734 if ((guard2 instanceof NotExpr)
00735 && ((NotExpr)guard2).getOp().equals(guard1))
00736 return true;
00737 return false;
00738 }
00739 static String locLabel(Location loc) {
00740 if (loc.getOutTrans().size() == 0)
00741 return "endloc_" + loc.getId();
00742 else
00743 return "loc_" + loc.getId();
00744 }
00745 static String locLabel(Location loc1, int branch, Location loc2) {
00746 return "loc_" + loc1.getId() + "_" + branch + "_" + loc2.getId();
00747 }
00748 boolean nonNegative(Expr expr) {
00749 if (expr instanceof ConstExpr)
00750 return ((ConstExpr)expr).getValue() >= 0;
00751 if (expr.getType() instanceof Range) {
00752 Range type = (Range) expr.getType();
00753 return (type.getFromVal().getValue() >= 0);
00754 }
00755 return false;
00756 }
00757 static int parseInt(String s) {
00758 try {
00759 int result = Integer.parseInt(s);
00760 return result;
00761 } catch (NumberFormatException e) {
00762 throw new RuntimeException("Integer didn't parse: " + s);
00763 }
00764 }
00765 void parseLine(String line, BirTrace trace) {
00766 int pos = line.indexOf("BIR:");
00767 if (pos >= 0) {
00768 StringTokenizer st =
00769 new StringTokenizer(line.substring(pos + 4));
00770 int locId = parseInt(st.nextToken());
00771 int transNum = parseInt(st.nextToken());
00772 int actionNum = parseInt(st.nextToken());
00773 String status = st.nextToken();
00774 Location loc = system.getLocation(locId);
00775 Transformation trans =
00776 loc.getOutTrans().elementAt(transNum);
00777 if (status.equals("OK")) {
00778 if (actionNum == 1)
00779 trace.addTrans(trans);
00780 }
00781 else
00782 trace.setTrap(status,trans,actionNum);
00783 return;
00784 }
00785 pos = line.indexOf("BIR?");
00786 if (pos >= 0) {
00787 StringTokenizer st =
00788 new StringTokenizer(line.substring(pos + 4));
00789 int actionNum = parseInt(st.nextToken());
00790 int choiceNum = parseInt(st.nextToken());
00791 trace.setChoice(actionNum,choiceNum);
00792 }
00793 }
00794
00795
00796
00797
00798
00799
00800
00801 public BirTrace parseOutput() {
00802 if (! ranVerifier)
00803 throw new RuntimeException("Did not run verifier on input");
00804 try {
00805 File sourceFile = new File(currentDir(),
00806 system.getName() + ".dprom");
00807 File trailFile = new File(currentDir(),
00808 system.getName() + ".dprom.trail");
00809 BirTrace trace = new BirTrace(system);
00810
00811 if (! trailFile.exists()) {
00812 trace.setVerified(true);
00813 return trace;
00814 }
00815 String output =
00816 execAndWait("dspin -t " + sourceFile.getAbsolutePath(), true);
00817 BufferedReader reader =
00818 new BufferedReader(new StringReader(output));
00819 String line = reader.readLine();
00820 while (line != null) {
00821 parseLine(line,trace);
00822 line = reader.readLine();
00823 }
00824 trace.done();
00825 trace.setVerified(false);
00826 return trace;
00827 } catch(IOException e) {
00828 throw new RuntimeException("Error parsing dSPIN output: \n" + e);
00829 }
00830 }
00831 void predicates() {
00832 println("/* Predicates */");
00833 Vector preds = system.getPredicates();
00834 for (int i = 0; i < preds.size(); i++) {
00835 Expr pred = (Expr) preds.elementAt(i);
00836 String name = system.predicateName(pred);
00837 inDefine = true;
00838 println("#define " + name + " ");
00839 indentLevel = 1;
00840 printGuard(applyTo(pred).getCase(normal));
00841 inDefine = false;
00842 println("");
00843 indentLevel = 0;
00844 }
00845 println("");
00846 }
00847 void print(String s) {
00848 if (newLine) {
00849 for (int i = 0; i < indentLevel; i++)
00850 out.print(" ");
00851 newLine = false;
00852 }
00853 out.print(s);
00854 }
00855 void printGuard(TreeNode tree) {
00856 if (tree instanceof ExprNode) {
00857 ExprNode node = (ExprNode) tree;
00858 print(node.expr1);
00859 }
00860 else if (tree instanceof TrapNode) {
00861 TrapNode node = (TrapNode) tree;
00862 print("TRAP");
00863 }
00864 else {
00865 CaseNode node = (CaseNode) tree;
00866 print("( ");
00867 for (int i = 0; i < node.size(); i++) {
00868 Case c = node.elementAt(i);
00869 indentLevel++;
00870 println("( " + c.cond);
00871 print("&& ");
00872 indentLevel++;
00873 printGuard(c.node);
00874 indentLevel--;
00875 print(" )");
00876 indentLevel--;
00877 if (i < node.size() - 1) {
00878 println();
00879 print("|| ");
00880 }
00881 }
00882 println(" )");
00883 }
00884 }
00885 void println() {
00886 if (inDefine)
00887 out.print("\\");
00888 out.println();
00889 newLine = true;
00890 }
00891 void println(String s) {
00892 print(s);
00893 println();
00894 }
00895 void printStatement(TreeNode tree) {
00896 if (tree instanceof ExprNode) {
00897 ExprNode node = (ExprNode) tree;
00898 println(node.expr1);
00899 }
00900 else if (tree instanceof TrapNode) {
00901 TrapNode node = (TrapNode) tree;
00902 print(" printf(\"BIR: " + actionId()
00903 + " " + node.desc + "\\n\"); ");
00904 if (node.fatal)
00905 println("assert(0);");
00906 else
00907 println("limit_exception = 1; goto endtrap;");
00908 }
00909 else {
00910 CaseNode node = (CaseNode) tree;
00911 println("if ");
00912 for (int i = 0; i < node.size(); i++) {
00913 Case c = node.elementAt(i);
00914 String cond = (i < node.size() - 1) ? c.cond : "else";
00915 println(":: " + cond + " -> ");
00916 indentLevel++;
00917 printStatement(c.node);
00918 indentLevel--;
00919 }
00920 println("fi; ");
00921 }
00922 }
00923 void property() {
00924 if (options.ApplyNeverClaim)
00925 println("#include \"" + system.getName() + ".never\"");
00926 }
00927 int refIndex(StateVar target) {
00928 return 1 + system.refAnyType().getTargets().indexOf(target);
00929 }
00930 void resetDeadVariables(Location fromLoc, Location toLoc) {
00931 StateVarVector liveBefore = fromLoc.getLiveVars();
00932 StateVarVector liveAfter = toLoc.getLiveVars();
00933 if (liveBefore != null && liveAfter!= null)
00934 for (int i = 0; i < liveBefore.size(); i++)
00935 if (liveAfter.indexOf(liveBefore.elementAt(i)) == -1) {
00936
00937 StateVar var = liveBefore.elementAt(i);
00938 var.apply(this);
00939 print(getSimpleResult() + " = ");
00940 var.getInitVal().apply(this);
00941 println(getSimpleResult() + ";");
00942 }
00943 }
00944 DSpinTrans run() {
00945 header();
00946 definitions();
00947 stateVariables();
00948 transitions();
00949 predicates();
00950 property();
00951 return this;
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961 public String runSpin() {
00962 try {
00963 if (options.ApplyNeverClaim) {
00964 File ltlFile = new File(currentDir(),
00965 system.getName() + ".spin.ltl");
00966 if (! ltlFile.exists())
00967 throw new RuntimeException("Cannot find LTL file: " +
00968 ltlFile.getAbsolutePath());
00969 String neverClaim =
00970 execAndWait("spin -F " + ltlFile.getAbsolutePath(), true);
00971 File neverFile = new File(currentDir(),
00972 system.getName() + ".never");
00973 FileOutputStream streamOut = new FileOutputStream(neverFile);
00974 PrintWriter writerOut = new PrintWriter(streamOut);
00975 writerOut.println(neverClaim);
00976 writerOut.close();
00977 }
00978 File sourceFile = new File(currentDir(),
00979 system.getName() + ".dprom");
00980 if (! sourceFile.exists())
00981 throw new RuntimeException("Cannot find dSPIN source file: " +
00982 sourceFile.getAbsolutePath());
00983 File trailFile = new File(currentDir(),
00984 system.getName() + ".dprom.trail");
00985 if (trailFile.exists())
00986 trailFile.delete();
00987 File panFile = new File(currentDir(),
00988 "pan.exe");
00989 execAndWait("dspin -a " + sourceFile.getAbsolutePath(), true);
00990 execAndWait(ccName + " " + options.compileOptions() +
00991 " -o pan.exe -I " + includeDir + " pan.c", true);
00992 ranVerifier = true;
00993 return execAndWait(panFile.getCanonicalPath() + " " +
00994 options.panOptions(), true);
00995
00996 } catch(Exception e)
00997 {
00998 throw new RuntimeException("Could not produce SPIN file (" + e + ")");
00999 }
01000 }
01001 TreeNode specialize(String expr) {
01002 return new CaseNode(new Case(normal, new ExprNode(expr)));
01003 }
01004 void stateVariables() {
01005 println("bool limit_exception = 0;");
01006 println("byte _i_ = 0;");
01007 println("object& _new_;");
01008 ThreadVector threads = system.getThreads();
01009 for (int i = 0; i < threads.size(); i++) {
01010 if (! threads.elementAt(i).isMain()) {
01011 println("chan _threadStart_" + i + " = [1] of { bit };");
01012 println("bit _threadActive_" + i + ";");
01013 }
01014 }
01015 println();
01016 StateVarVector stateVarVector = system.getStateVars();
01017 for (int i = 0; i < stateVarVector.size(); i++) {
01018 StateVar var = stateVarVector.elementAt(i);
01019 String refIndex = " ";
01020 if (var.getType().isKind(COLLECTION))
01021 println("/* Collection: " + var.getName() + ", ref index = "
01022 + refIndex(var) + " */");
01023 else {
01024 if (var.getType().isKind(RECORD|ARRAY))
01025 refIndex += "/* ref index = " + refIndex(var) + " */";
01026 println(dSpinTypeName(var.getType(),null) + " "
01027 + var.getName() + ";" + refIndex);
01028 }
01029 }
01030 println();
01031 }
01032 void transitions() {
01033 ThreadVector threadVector = system.getThreads();
01034 for (int i = 0; i < threadVector.size(); i++) {
01035 BirThread thread = threadVector.elementAt(i);
01036 println("proctype " + thread.getName() + "() { ");
01037 println(" int _temp_;");
01038 if (! thread.isMain())
01039 println("endtop_" + i + ":\n _beginThread_" + i + ";");
01040 LocVector threadLocVector = thread.getLocations();
01041 for (int j = 0; j < threadLocVector.size(); j++)
01042 translateLocation(threadLocVector.elementAt(j));
01043 println("endtrap:");
01044 println(" 0;");
01045 println("}");
01046 println();
01047 }
01048 initBlock();
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058 public static DSpinTrans translate(TransSystem system) {
01059 return translate(system,null);
01060 }
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 public static DSpinTrans translate(TransSystem system,
01073 DSpinOptions options) {
01074 try {
01075 File sourceFile = new File(currentDir(),
01076 system.getName() + ".dprom");
01077
01078 FileOutputStream streamOut = new FileOutputStream(sourceFile);
01079 PrintWriter writerOut = new PrintWriter(streamOut);
01080 DSpinTrans result = translate(system, options, writerOut);
01081 writerOut.close();
01082 return result;
01083 } catch(IOException e)
01084 {
01085 throw new RuntimeException("Could not produce dSPIN file: " + e);
01086 }
01087 }
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 public static DSpinTrans translate(TransSystem system,
01098 DSpinOptions options,
01099 PrintWriter out) {
01100 return (new DSpinTrans(system,options,out)).run();
01101 }
01102 void translateBinaryOp(Expr e1, Expr e2, String op) {
01103 TreeNode e1Tree = applyTo(e1);
01104 TreeNode e2Tree = applyTo(e2);
01105 TreeNode result = e1Tree.compose(e2Tree,null);
01106 Vector leaves = result.getLeaves(new Vector());
01107 for (int i = 0; i < leaves.size(); i++) {
01108 ExprNode leaf = (ExprNode) leaves.elementAt(i);
01109 leaf.update("(" + leaf.expr1 + op + leaf.expr2 + ")");
01110 }
01111 setResult(result);
01112 }
01113 public void translateLocation(Location loc)
01114 {
01115 if (! loc.isVisible())
01116 return;
01117 println(locLabel(loc) + ":");
01118 indentLevel++;
01119 TransVector outTrans = loc.getOutTrans();
01120 if (outTrans.size() == 1)
01121 translateSequence(outTrans.elementAt(0),0);
01122 else if (outTrans.size() == 0)
01123 println("0;");
01124 else {
01125 println("if");
01126 for (int i = 0; i < outTrans.size(); i++) {
01127 print(":: ");
01128 indentLevel++;
01129 translateSequence(outTrans.elementAt(i),i);
01130 indentLevel--;
01131 }
01132 println("fi;");
01133 }
01134 indentLevel--;
01135 }
01136 void translateSeq(LocVector locSet, Transformation trans,
01137 int branch, boolean supressGuard) {
01138 translateTrans(trans, supressGuard);
01139 if (trans.getToLoc().isVisible()) {
01140 resetDeadVariables(locSet.firstElement(), trans.getToLoc());
01141 println("goto " + locLabel(trans.getToLoc()) + ";");
01142 }
01143 else if (locSet.contains(trans.getToLoc()))
01144 println("goto " +
01145 locLabel(locSet.firstElement(),branch,trans.getToLoc())
01146 + ";");
01147 else {
01148 locSet.addElement(trans.getToLoc());
01149 if (trans.getToLoc().getInTrans().size() > 1)
01150 println(locLabel(locSet.firstElement(),branch,trans.getToLoc())
01151 + ":");
01152 TransVector successors = trans.getToLoc().getOutTrans();
01153 if (successors.size() == 1)
01154 translateSeq(locSet, successors.elementAt(0), branch,false);
01155 else if (isIfBranch(successors)) {
01156 println("if");
01157 print(":: ");
01158 indentLevel++;
01159 translateSeq(locSet, successors.elementAt(0), branch, false);
01160 indentLevel--;
01161 print(":: else -> ");
01162 indentLevel++;
01163 translateSeq(locSet, successors.elementAt(1), branch, true);
01164 indentLevel--;
01165 println("fi;");
01166 }
01167 else {
01168 println("if");
01169 for (int i = 0; i < successors.size(); i++) {
01170 print(":: ");
01171 indentLevel++;
01172 translateSeq(locSet, successors.elementAt(i),branch,false);
01173 indentLevel--;
01174 }
01175 println("fi;");
01176 }
01177 }
01178 }
01179 void translateSequence(Transformation trans, int branch) {
01180 Location startLoc = trans.getFromLoc();
01181 println("atomic { ");
01182 indentLevel++;
01183 translateSeq(new LocVector(startLoc), trans, branch, false);
01184 indentLevel--;
01185 println("}");
01186 }
01187 void translateTrans(Transformation trans, boolean supressGuard)
01188 {
01189 currentTrans = trans;
01190 actionNum = 0;
01191 if (! supressGuard && guardPresent(trans)) {
01192 printGuard(applyTo(trans.getGuard()).getCase(normal));
01193 println("-> ");
01194 }
01195 ActionVector actions = trans.getActions();
01196 for (int i = 0; i < actions.size(); i++) {
01197 actionNum = i + 1;
01198 println("printf(\"BIR: " + actionId() + " OK\\n\"); ");
01199 actions.elementAt(i).apply(this);
01200 }
01201 if (resetTemp) {
01202 println("_temp_ = 0;");
01203 resetTemp = false;
01204 }
01205 if (resetNew) {
01206 println("_new_ = null;");
01207 resetNew = false;
01208 }
01209 }
01210 void translateUnaryOp(Expr e, String op) {
01211 TreeNode result = applyTo(e);
01212 Vector leaves = result.getLeaves(new Vector());
01213 for (int i = 0; i < leaves.size(); i++) {
01214 ExprNode leaf = (ExprNode) leaves.elementAt(i);
01215 leaf.update("(" + op + leaf.expr1 + ")");
01216 }
01217 setResult(result);
01218 }
01219 }