diff --git a/.gitignore b/.gitignore
index 112ffa08d8..507ff2a3d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@ dest/
# Other
wdl-output.json
+witness.graphml
diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/debug/ARGWebDebugger.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/debug/ARGWebDebugger.java
index a337da7364..92b2a67313 100644
--- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/debug/ARGWebDebugger.java
+++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/debug/ARGWebDebugger.java
@@ -33,7 +33,7 @@
*/
public final class ARGWebDebugger {
- private static final boolean debug = false;
+ public static boolean on = false;
private static final Integer PORT = 8080;
private static SocketIOServer server;
@@ -49,7 +49,7 @@ private ARGWebDebugger() {
}
private static void startServer() {
- if (!debug) return;
+ if (!on) return;
Configuration config = new Configuration();
config.setPort(PORT);
@@ -107,7 +107,7 @@ private static String nodeToString(ArgNode extends State, ?
}
public static void create(ArgNode extends State, ? extends Action> initNode) {
- if (!debug) {
+ if (!on) {
return;
}
replayLog.clear();
@@ -118,7 +118,7 @@ public static void create(ArgNode extends State, ? extends Action> initNode) {
public static void add(ArgNode extends State, ? extends Action> parent,
A action,
ArgNode extends State, ? extends Action> child) {
- if (!debug) {
+ if (!on) {
return;
}
send("{\"method\": \"add\", \"parent\": " + parent.getId() + ", \"child\": " + nodeToString(child, action) + "}", true);
@@ -126,7 +126,7 @@ public static void add(ArgNode extends State, ? extends Act
}
public static void remove(ArgEdge extends State, ? extends Action> edge) {
- if (!debug) {
+ if (!on) {
return;
}
send("{\"method\": \"delete\", \"parent\": " + edge.getSource().getId() + ", \"child\": " + edge.getTarget().getId() + "}", true);
diff --git a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/expression/ExpressionVisitor.java b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/expression/ExpressionVisitor.java
index 084dd96d50..ca60f10874 100644
--- a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/expression/ExpressionVisitor.java
+++ b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/expression/ExpressionVisitor.java
@@ -393,6 +393,8 @@ public Expr> visitMultiplicativeExpression(CParser.MultiplicativeExpressionCon
case "%":
if (leftExpr.getType() instanceof IntType && rightExpr.getType() instanceof IntType) {
expr = createIntMod(leftExpr, rightExpr);
+ } else if (leftExpr.getType() instanceof BvType && rightExpr.getType() instanceof BvType) {
+ expr = AbstractExprs.Rem(leftExpr, rightExpr);
} else {
expr = AbstractExprs.Mod(leftExpr, rightExpr);
}
diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarConfig.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarConfig.kt
index 1b8c862699..9a42d21ba3 100644
--- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarConfig.kt
+++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarConfig.kt
@@ -221,7 +221,7 @@ data class XcfaCegarConfig(
ProcessHandle.current().info().command().orElse("java")
fun checkInProcess(xcfa: XCFA, smtHome: String, writeWitness: Boolean, sourceFileName: String,
- logger: Logger, parseContext: ParseContext): () -> SafetyResult<*, *> {
+ logger: Logger, parseContext: ParseContext, argdebug: Boolean): () -> SafetyResult<*, *> {
val pb = NuProcessBuilder(listOf(
getJavaExecutable(),
"-cp",
@@ -233,8 +233,9 @@ data class XcfaCegarConfig(
"" + !writeWitness,
"--input",
sourceFileName,
- "--gzip"
- ))
+ "--gzip",
+ if (argdebug) "--arg-debug" else null,
+ ).filterNotNull())
val processHandler = ProcessHandler(logger)
pb.setProcessListener(processHandler)
val process: NuProcess = pb.start()
diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarServer.java b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarServer.java
index e7654daf7e..440b2d2d35 100644
--- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarServer.java
+++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCegarServer.java
@@ -22,6 +22,7 @@
import com.google.common.base.Stopwatch;
import com.google.gson.Gson;
import hu.bme.mit.theta.analysis.algorithm.SafetyResult;
+import hu.bme.mit.theta.analysis.algorithm.debug.ARGWebDebugger;
import hu.bme.mit.theta.analysis.expr.ExprAction;
import hu.bme.mit.theta.analysis.expr.ExprState;
import hu.bme.mit.theta.common.logging.ConsoleLabelledLogger;
@@ -29,6 +30,9 @@
import hu.bme.mit.theta.common.logging.Logger.Level;
import hu.bme.mit.theta.frontend.ParseContext;
import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager;
+import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiKt;
+import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread;
+import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiSingleThread;
import hu.bme.mit.theta.xcfa.cli.utils.XcfaWitnessWriter;
import hu.bme.mit.theta.xcfa.model.XCFA;
@@ -79,6 +83,11 @@ class XcfaCegarServer {
@Parameter(names = "--debug", description = "Debug mode (will not create a socket)")
Boolean debug = false;
+
+ @Parameter(names = "--arg-debug", description = "ARG debug mode (use the web-based debugger for ARG visualization)")
+ Boolean argdebug = false;
+
+
@Parameter(names = "--gzip", description = "Expect stdin to contain gzipped text")
Boolean gzip = false;
@@ -92,6 +101,8 @@ private void run(String[] args) {
System.exit(ExitCodes.INVALID_PARAM.getCode());
}
+ if (argdebug) ARGWebDebugger.on = true;
+
final Logger logger = new ConsoleLabelledLogger();
exitOnError(true, debug, () -> {
@@ -159,6 +170,10 @@ private void run(String[] args) {
System.err.println("Erroneous parsecontext, see file " + tempFile.getAbsolutePath());
throw e;
}
+ XcfaCoiKt.ConeOfInfluence =
+ (parseContext.getMultiThreading()) ?
+ new XcfaCoiMultiThread(xcfa) :
+ new XcfaCoiSingleThread(xcfa);
logger.write(Logger.Level.INFO, "Parsed parsecontext.\n");
diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt
index 6ae1ec6815..fb4b685a6f 100644
--- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt
+++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt
@@ -24,6 +24,7 @@ import com.google.gson.GsonBuilder
import com.google.gson.JsonParser
import hu.bme.mit.theta.analysis.Trace
import hu.bme.mit.theta.analysis.algorithm.SafetyResult
+import hu.bme.mit.theta.analysis.algorithm.debug.ARGWebDebugger
import hu.bme.mit.theta.analysis.expl.ExplState
import hu.bme.mit.theta.analysis.utils.ArgVisualizer
import hu.bme.mit.theta.analysis.utils.TraceVisualizer
@@ -112,6 +113,10 @@ class XcfaCli(private val args: Array) {
@Parameter(names = ["--debug"], description = "Debug mode (not exiting when encountering an exception)")
var debug: Boolean = false
+ @Parameter(names = ["--arg-debug"],
+ description = "ARG debug mode (use the web-based debugger for ARG visualization)")
+ var argdebug: Boolean = false
+
//////////// debug options ////////////
@Parameter(names = ["--stacktrace"],
description = "Print full stack trace in case of exception")
@@ -205,6 +210,7 @@ class XcfaCli(private val args: Array) {
WebDebuggerLogger.getInstance().setTitle(input?.name)
}
LoopUnrollPass.UNROLL_LIMIT = loopUnroll
+ ARGWebDebugger.on = argdebug
logger.write(Logger.Level.INFO, "Parsing the input $input as $inputType\n")
val parseContext = ParseContext()
@@ -237,9 +243,9 @@ class XcfaCli(private val args: Array) {
val safetyResult: SafetyResult<*, *> =
when (strategy) {
Strategy.DIRECT -> runDirect(xcfa, config, logger)
- Strategy.SERVER -> runServer(xcfa, config, logger, parseContext)
+ Strategy.SERVER -> runServer(xcfa, config, logger, parseContext, argdebug)
Strategy.SERVER_DEBUG -> runServerDebug(xcfa, config, logger, parseContext)
- Strategy.PORTFOLIO -> runPortfolio(xcfa, explicitProperty, logger, parseContext, debug)
+ Strategy.PORTFOLIO -> runPortfolio(xcfa, explicitProperty, logger, parseContext, debug, argdebug)
}
// post verification
postVerificationLogging(safetyResult, parseContext)
@@ -250,9 +256,9 @@ class XcfaCli(private val args: Array) {
exitOnError(stacktrace, debug) { config.check(xcfa, logger) }
private fun runServer(xcfa: XCFA, config: XcfaCegarConfig,
- logger: ConsoleLogger, parseContext: ParseContext): SafetyResult<*, *> {
+ logger: ConsoleLogger, parseContext: ParseContext, argdebug: Boolean): SafetyResult<*, *> {
val safetyResultSupplier = config.checkInProcess(xcfa, solverHome, true,
- input!!.absolutePath, logger, parseContext)
+ input!!.absolutePath, logger, parseContext, argdebug)
return try {
safetyResultSupplier()
} catch (e: ErrorCodeException) {
@@ -272,10 +278,11 @@ class XcfaCli(private val args: Array) {
}
private fun runPortfolio(xcfa: XCFA, explicitProperty: ErrorDetection,
- logger: ConsoleLogger, parseContext: ParseContext, debug: Boolean = false): SafetyResult<*, *> {
+ logger: ConsoleLogger, parseContext: ParseContext, debug: Boolean = false,
+ argdebug: Boolean): SafetyResult<*, *> {
return try {
val portfolioResult = if (File(portfolio).exists()) {
- val portfolioDescriptor = portfolio!!.lowercase() + ".kts"
+ val portfolioDescriptor = portfolio!!
val kotlinEngine: ScriptEngine = ScriptEngineManager().getEngineByExtension("kts")
val bindings: Bindings = kotlinEngine.createBindings()
bindings["xcfa"] = xcfa
@@ -288,6 +295,7 @@ class XcfaCli(private val args: Array) {
multithreaded = parseContext.multiThreading,
arithmetic = parseContext.bitwiseOption,
)
+ bindings["argdebug"] = argdebug
kotlinEngine as Compilable
val stopwatch = Stopwatch.createStarted()
@@ -308,7 +316,7 @@ class XcfaCli(private val args: Array) {
complexPortfolio(xcfa, input!!.absolutePath, logger, solverHome, VerificationTraits(
multithreaded = parseContext.multiThreading,
arithmetic = parseContext.bitwiseOption,
- ), explicitProperty, parseContext)
+ ), explicitProperty, parseContext, argdebug)
} else throw Exception("No known portfolio $portfolio")
concretizerSolver = portfolioResult.first.refinementSolver
diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/portfolio/complex.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/portfolio/complex.kt
index 9b7d886700..7cb069a80a 100644
--- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/portfolio/complex.kt
+++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/portfolio/complex.kt
@@ -27,11 +27,13 @@ import hu.bme.mit.theta.xcfa.model.XCFA
fun complexPortfolio(xcfaTyped: XCFA, cFileNameTyped: String, loggerTyped: Logger, smtHomeTyped: String,
traitsTyped: VerificationTraits, propertyTyped: ErrorDetection,
- parseContextTyped: ParseContext): Pair> {
+ parseContextTyped: ParseContext,
+ argdebug: Boolean): Pair> {
val checker = { p: Boolean, config: XcfaCegarConfig ->
if (p)
- config.checkInProcess(xcfaTyped, smtHomeTyped, true, cFileNameTyped, loggerTyped, parseContextTyped)()
+ config.checkInProcess(xcfaTyped, smtHomeTyped, true, cFileNameTyped, loggerTyped, parseContextTyped,
+ argdebug)()
else config.check(xcfaTyped, loggerTyped)
}