From 292dd94b789382e9ff453b7275c105dee04ade91 Mon Sep 17 00:00:00 2001 From: RipplB Date: Thu, 18 Jul 2024 13:17:15 +0200 Subject: [PATCH 01/21] Generalize abstractor, refiner, cegarchecker, visualizer These classes/interfaces depended on ARG and Trace before, which heavily limits reusability. They are now generalized over Witness and Cex. To ease the switch, the old entry points are replicated in "Arg..." classes, so a lot of these changes are just renames. --- build.gradle.kts | 2 +- .../cfa/analysis/config/CfaConfigBuilder.java | 433 ++++++++++--- .../analysis/algorithm/cegar/Abstractor.java | 22 +- .../algorithm/cegar/ArgAbstractor.java | 28 + .../algorithm/cegar/ArgCegarChecker.java | 48 ++ .../analysis/algorithm/cegar/ArgRefiner.java | 29 + ...bstractor.java => BasicArgAbstractor.java} | 12 +- .../algorithm/cegar/CegarChecker.java | 59 +- .../analysis/algorithm/cegar/Refiner.java | 18 +- .../algorithm/cegar/RefinerResult.java | 44 +- .../expr/refinement/AasporRefiner.java | 15 +- .../refinement/MultiExprTraceRefiner.java | 16 +- .../refinement/SingleExprTraceRefiner.java | 6 +- .../theta/analysis/utils/ArgVisualizer.java | 7 +- .../analysis/utils/WitnessVisualizer.java | 26 + .../multi/config/StmtMultiConfigBuilder.kt | 350 ++++++++--- .../sts/analysis/config/StsConfigBuilder.java | 196 +++--- .../mit/theta/sts/analysis/StsExplTest.java | 10 +- .../mit/theta/sts/analysis/StsPredTest.java | 10 +- .../mit/theta/xcfa/analysis/XcfaAbstractor.kt | 137 ---- .../mit/theta/xcfa/analysis/XcfaAnalysis.kt | 496 +++++++++------ .../theta/xcfa/analysis/XcfaArgAbstractor.kt | 143 +++++ .../analysis/XcfaSingeExprTraceRefiner.kt | 4 +- .../xcfa/analysis/XcfaExplAnalysisTest.kt | 549 ++++++++-------- .../xcfa/analysis/XcfaPredAnalysisTest.kt | 563 +++++++++-------- .../xcfa/cli/checkers/ConfigToCegarChecker.kt | 63 +- .../mit/theta/xcfa/cli/params/ParamValues.kt | 592 ++++++++++-------- .../analysis/config/XstsConfigBuilder.java | 256 +++++--- .../theta/xta/analysis/XtaAnalysisTest.java | 8 +- .../xta/analysis/XtaZoneAnalysisTest.java | 8 +- 30 files changed, 2536 insertions(+), 1614 deletions(-) create mode 100644 subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgAbstractor.java create mode 100644 subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java create mode 100644 subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java rename subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/{BasicAbstractor.java => BasicArgAbstractor.java} (91%) create mode 100644 subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java delete mode 100644 subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAbstractor.kt create mode 100644 subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaArgAbstractor.kt diff --git a/build.gradle.kts b/build.gradle.kts index b76fd9f7ff..06036a38d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,7 +29,7 @@ buildscript { allprojects { group = "hu.bme.mit.theta" - version = "6.6.3" + version = "6.6.4" apply(from = rootDir.resolve("gradle/shared-with-buildSrc/mirrors.gradle.kts")) } diff --git a/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java b/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java index 7427f38b20..37c30260ea 100644 --- a/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java +++ b/subprojects/cfa/cfa-analysis/src/main/java/hu/bme/mit/theta/cfa/analysis/config/CfaConfigBuilder.java @@ -15,16 +15,19 @@ */ package hu.bme.mit.theta.cfa.analysis.config; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; + import hu.bme.mit.theta.analysis.*; +import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators.ArgNodeComparator; -import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterion; import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions; import hu.bme.mit.theta.analysis.expl.*; @@ -52,14 +55,10 @@ import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.SolverFactory; - import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.True; - public class CfaConfigBuilder { private final SolverFactory abstractionSolverFactory; @@ -75,16 +74,19 @@ public class CfaConfigBuilder { private InitPrec initPrec = InitPrec.EMPTY; private PruneStrategy pruneStrategy = PruneStrategy.LAZY; - public CfaConfigBuilder(final Domain domain, final Refinement refinement, - final SolverFactory solverFactory) { + public CfaConfigBuilder( + final Domain domain, final Refinement refinement, final SolverFactory solverFactory) { this.domain = domain; this.refinement = refinement; this.abstractionSolverFactory = solverFactory; this.refinementSolverFactory = solverFactory; } - public CfaConfigBuilder(final Domain domain, final Refinement refinement, - final SolverFactory abstractionSolverFactory, final SolverFactory refinementSolverFactory) { + public CfaConfigBuilder( + final Domain domain, + final Refinement refinement, + final SolverFactory abstractionSolverFactory, + final SolverFactory refinementSolverFactory) { this.domain = domain; this.refinement = refinement; this.abstractionSolverFactory = abstractionSolverFactory; @@ -131,12 +133,13 @@ public CfaConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { return this; } - public CfaConfig build(final CFA cfa, - final CFA.Loc errLoc) { + public CfaConfig build( + final CFA cfa, final CFA.Loc errLoc) { if (domain == Domain.EXPL) { return (new ExplStrategy(cfa)).buildConfig(errLoc); } - if (domain == Domain.PRED_BOOL || domain == Domain.PRED_CART + if (domain == Domain.PRED_BOOL + || domain == Domain.PRED_CART || domain == Domain.PRED_SPLIT) { return (new PredStrategy(cfa)).buildConfig(errLoc); } @@ -166,18 +169,53 @@ public enum Domain { public enum Refinement { FW_BIN_ITP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceFwBinItpChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createItpSolver()), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceFwBinItpChecker.create( + True(), + True(), + builderStrategy.getRefinementSolverFactory().createItpSolver()), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, BW_BIN_ITP { + }, + BW_BIN_ITP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceBwBinItpChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createItpSolver()), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + True(), + True(), + builderStrategy.getRefinementSolverFactory().createItpSolver()), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, SEQ_ITP { + }, + SEQ_ITP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceSeqItpChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createItpSolver()), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceSeqItpChecker.create( + True(), + True(), + builderStrategy.getRefinementSolverFactory().createItpSolver()), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } }, MULTI_SEQ { @@ -187,60 +225,229 @@ public StopCriterion getStopCriterion() { } @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return MultiExprTraceRefiner.create(ExprTraceSeqItpChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createItpSolver()), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return MultiExprTraceRefiner.create( + ExprTraceSeqItpChecker.create( + True(), + True(), + builderStrategy.getRefinementSolverFactory().createItpSolver()), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } }, UNSAT_CORE { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceUnsatCoreChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getVarsRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceUnsatCoreChecker.create( + True(), + True(), + builderStrategy.getRefinementSolverFactory().createUCSolver()), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getVarsRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, UCB { + }, + UCB { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceUCBChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceUCBChecker.create( + True(), + True(), + builderStrategy.getRefinementSolverFactory().createUCSolver()), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } }, NWT_WP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withoutIT().withSP().withoutLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withoutIT() + .withSP() + .withoutLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_SP { + }, + NWT_SP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withoutIT().withWP().withoutLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withoutIT() + .withWP() + .withoutLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_WP_LV { + }, + NWT_WP_LV { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withoutIT().withWP().withLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withoutIT() + .withWP() + .withLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_SP_LV { + }, + NWT_SP_LV { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withoutIT().withSP().withLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withoutIT() + .withSP() + .withLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_IT_WP { + }, + NWT_IT_WP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withIT().withWP().withoutLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withIT() + .withWP() + .withoutLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_IT_SP { + }, + NWT_IT_SP { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withIT().withSP().withoutLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withIT() + .withSP() + .withoutLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_IT_WP_LV { + }, + NWT_IT_WP_LV { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withIT().withWP().withLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withIT() + .withWP() + .withLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } - }, NWT_IT_SP_LV { + }, + NWT_IT_SP_LV { @Override - public Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy) { - return SingleExprTraceRefiner.create(ExprTraceNewtonChecker.create(True(), True(), builderStrategy.getRefinementSolverFactory().createUCSolver()).withIT().withSP().withLV(), builderStrategy.getPrecGranularity().createRefiner(builderStrategy.getItpRefToPrec()), builderStrategy.getPruneStrategy(), builderStrategy.getLogger()); + public + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy) { + return SingleExprTraceRefiner.create( + ExprTraceNewtonChecker.create( + True(), + True(), + builderStrategy + .getRefinementSolverFactory() + .createUCSolver()) + .withIT() + .withSP() + .withLV(), + builderStrategy + .getPrecGranularity() + .createRefiner(builderStrategy.getItpRefToPrec()), + builderStrategy.getPruneStrategy(), + builderStrategy.getLogger()); } }; @@ -248,24 +455,25 @@ public StopCriterion getStopCriterion() { return StopCriterions.firstCex(); } - public abstract Refiner, CfaAction, CfaPrec

> getRefiner(BuilderStrategy builderStrategy); - + public abstract + ArgRefiner, CfaAction, CfaPrec

> getRefiner( + BuilderStrategy builderStrategy); } public enum Search { BFS { @Override public ArgNodeComparator getComp(final CFA cfa, final CFA.Loc errLoc) { - return ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), - ArgNodeComparators.bfs()); + return ArgNodeComparators.combine( + ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()); } }, DFS { @Override public ArgNodeComparator getComp(final CFA cfa, final CFA.Loc errLoc) { - return ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), - ArgNodeComparators.dfs()); + return ArgNodeComparators.combine( + ArgNodeComparators.targetFirst(), ArgNodeComparators.dfs()); } }, @@ -277,7 +485,6 @@ public ArgNodeComparator getComp(final CFA cfa, final CFA.Loc errLoc) { }; public abstract ArgNodeComparator getComp(CFA cfa, CFA.Loc errLoc); - } public enum PredSplit { @@ -302,8 +509,9 @@ public

CfaPrec

createPrec(final P innerPrec) { } @Override - public PrecRefiner, A, CfaPrec

, R> createRefiner( - final RefutationToPrec refToPrec) { + public + PrecRefiner, A, CfaPrec

, R> createRefiner( + final RefutationToPrec refToPrec) { return GlobalCfaPrecRefiner.create(refToPrec); } @@ -320,8 +528,9 @@ public

CfaPrec

createPrec(final P innerPrec) { } @Override - public PrecRefiner, A, CfaPrec

, R> createRefiner( - final RefutationToPrec refToPrec) { + public + PrecRefiner, A, CfaPrec

, R> createRefiner( + final RefutationToPrec refToPrec) { return LocalCfaPrecRefiner.create(refToPrec); } @@ -333,8 +542,10 @@ public CfaPrec assumePrecs(CFA cfa) { public abstract

CfaPrec

createPrec(P innerPrec); - public abstract PrecRefiner, A, CfaPrec

, R> createRefiner( - RefutationToPrec refToPrec); + public abstract < + S extends ExprState, A extends Action, P extends Prec, R extends Refutation> + PrecRefiner, A, CfaPrec

, R> createRefiner( + RefutationToPrec refToPrec); public abstract CfaPrec assumePrecs(CFA cfa); } @@ -358,19 +569,37 @@ public CfaLts getLts(CFA.Loc errorLoc) { } public enum InitPrec { - EMPTY, ALLVARS, ALLASSUMES + EMPTY, + ALLVARS, + ALLASSUMES } public abstract class BuilderStrategy { - protected static final String UNSUPPORTED_CONFIG_VALUE = "Builder strategy %s does not support configuration value %s as %s"; + protected static final String UNSUPPORTED_CONFIG_VALUE = + "Builder strategy %s does not support configuration value %s as %s"; protected final CFA cfa; @SuppressWarnings("java:S1699") protected BuilderStrategy(CFA cfa) { - checkState(getSupportedDomains().contains(domain), UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), domain, "domain"); - checkState(getSupportedRefinements().contains(refinement), UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), refinement, "refinement"); - checkState(getSupportedInitPrecs().contains(initPrec), UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), initPrec, "initial precision"); + checkState( + getSupportedDomains().contains(domain), + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + domain, + "domain"); + checkState( + getSupportedRefinements().contains(refinement), + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + refinement, + "refinement"); + checkState( + getSupportedInitPrecs().contains(initPrec), + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + initPrec, + "initial precision"); this.cfa = cfa; } @@ -389,7 +618,10 @@ public CfaAnalysis getAnalysis() { public abstract RefutationToPrec getItpRefToPrec(); public RefutationToPrec getVarsRefToPrec() { - throw new UnsupportedOperationException(String.format("Builder strategy %s can not provide Vars refutation to precision", getClass().getSimpleName())); + throw new UnsupportedOperationException( + String.format( + "Builder strategy %s can not provide Vars refutation to precision", + getClass().getSimpleName())); } protected SolverFactory getRefinementSolverFactory() { @@ -421,22 +653,30 @@ public CfaLts getLts() { public CfaConfig, CfaAction, CfaPrec

> buildConfig(CFA.Loc errLoc) { final Predicate> target = new CfaErrorlocPredicate<>(errLoc); final Analysis, CfaAction, CfaPrec

> analysis = getAnalysis(); - final ArgBuilder, CfaAction, CfaPrec

> argBuilder = ArgBuilder.create( - getLts(errLoc), analysis, target, - true); - final Abstractor, CfaAction, CfaPrec

> abstractor = BasicAbstractor.builder( - argBuilder) - .waitlist(PriorityWaitlist.create(search.getComp(cfa, errLoc))) - .stopCriterion(refinement.getStopCriterion()) - .logger(logger).build(); - final Refiner, CfaAction, CfaPrec

> refiner = refinement.getRefiner(this); - final SafetyChecker, CfaAction>, Trace, CfaAction>, CfaPrec

> checker = CegarChecker.create( - abstractor, refiner, - logger); + final ArgBuilder, CfaAction, CfaPrec

> argBuilder = + ArgBuilder.create(getLts(errLoc), analysis, target, true); + final ArgAbstractor, CfaAction, CfaPrec

> abstractor = + BasicArgAbstractor.builder(argBuilder) + .waitlist(PriorityWaitlist.create(search.getComp(cfa, errLoc))) + .stopCriterion(refinement.getStopCriterion()) + .logger(logger) + .build(); + final ArgRefiner, CfaAction, CfaPrec

> refiner = + refinement.getRefiner(this); + final SafetyChecker< + ARG, CfaAction>, Trace, CfaAction>, CfaPrec

> + checker = ArgCegarChecker.create(abstractor, refiner, logger); return CfaConfig.create(checker, createInitPrec()); } - public MultiAnalysisSide, S, CfaState, CfaAction, CfaPrec

, CfaPrec> getMultiSide() { + public MultiAnalysisSide< + CfaState, + S, + CfaState, + CfaAction, + CfaPrec

, + CfaPrec> + getMultiSide() { return new MultiAnalysisSide<>( getAnalysis(), CfaControlInitFuncKt.cfaControlInitFunc(cfa.getInitLoc()), @@ -470,7 +710,8 @@ public Set getSupportedInitPrecs() { @Override public Analysis getDataAnalysis() { - return ExplStmtAnalysis.create(abstractionSolverFactory.createSolver(), True(), maxEnum); + return ExplStmtAnalysis.create( + abstractionSolverFactory.createSolver(), True(), maxEnum); } @Override @@ -489,7 +730,12 @@ public CfaPrec createInitPrec() { case EMPTY -> precGranularity.createPrec(ExplPrec.empty()); case ALLVARS -> precGranularity.createPrec(ExplPrec.of(cfa.getVars())); default -> - throw new UnsupportedOperationException(String.format(UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), initPrec, "initial precision")); + throw new UnsupportedOperationException( + String.format( + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + initPrec, + "initial precision")); }; } } @@ -520,8 +766,7 @@ public Set getSupportedRefinements() { Refinement.NWT_IT_SP, Refinement.NWT_IT_WP, Refinement.NWT_IT_SP_LV, - Refinement.NWT_IT_WP_LV - ); + Refinement.NWT_IT_WP_LV); } @Override @@ -546,9 +791,13 @@ public CfaPrec createInitPrec() { case EMPTY -> precGranularity.createPrec(PredPrec.of()); case ALLASSUMES -> precGranularity.assumePrecs(cfa); default -> - throw new UnsupportedOperationException(String.format(UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), initPrec, "initial precision")); + throw new UnsupportedOperationException( + String.format( + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + initPrec, + "initial precision")); }; } } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java index a7eb473efd..a6cb49bb43 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java @@ -15,31 +15,23 @@ */ package hu.bme.mit.theta.analysis.algorithm.cegar; -import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Prec; -import hu.bme.mit.theta.analysis.State; -import hu.bme.mit.theta.analysis.algorithm.arg.ARG; +import hu.bme.mit.theta.analysis.algorithm.Witness; /** - * Common interface for the abstractor component. It can create an initial ARG and check an ARG with + * Common interface for the abstractor component. It can create an initial witness and check a witness with * a given precision. */ -public interface Abstractor { +public interface Abstractor

{ /** - * Create initial ARG. - * - * @return + * Create initial witness */ - ARG createArg(); + W createWitness(); /** - * Check ARG with given precision. - * - * @param arg - * @param prec - * @return + * Check witness with given precision */ - AbstractorResult check(ARG arg, P prec); + AbstractorResult check(W witness, P prec); } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgAbstractor.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgAbstractor.java new file mode 100644 index 0000000000..67890b8a3a --- /dev/null +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgAbstractor.java @@ -0,0 +1,28 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.analysis.algorithm.cegar; + +import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Prec; +import hu.bme.mit.theta.analysis.State; +import hu.bme.mit.theta.analysis.algorithm.arg.ARG; + +/** + * Common interface for the abstractor component. It can create an initial ARG and check an ARG with + * a given precision. + */ +public interface ArgAbstractor + extends Abstractor> {} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java new file mode 100644 index 0000000000..06260c732c --- /dev/null +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java @@ -0,0 +1,48 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.analysis.algorithm.cegar; + +import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Prec; +import hu.bme.mit.theta.analysis.State; +import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.algorithm.arg.ARG; +import hu.bme.mit.theta.analysis.utils.ArgVisualizer; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.common.logging.NullLogger; + +/** + * Counterexample-Guided Abstraction Refinement (CEGAR) loop implementation, + * that uses an Abstractor to explore the abstract state space and a Refiner to + * check counterexamples and refine them if needed. It also provides certain + * statistics about its execution. + */ +public final class ArgCegarChecker { + + private ArgCegarChecker() { + } + + public static CegarChecker, Trace> create( + final ArgAbstractor abstractor, final ArgRefiner refiner) { + return create(abstractor, refiner, NullLogger.getInstance()); + } + + public static CegarChecker, Trace> create( + final ArgAbstractor abstractor, final ArgRefiner refiner, final Logger logger) { + return CegarChecker.create(abstractor, refiner, logger, ArgVisualizer.getDefault()); + } + +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java new file mode 100644 index 0000000000..2683a2fd0f --- /dev/null +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java @@ -0,0 +1,29 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.analysis.algorithm.cegar; + +import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Prec; +import hu.bme.mit.theta.analysis.State; +import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.algorithm.arg.ARG; + +/** + * Common interface for refiners. It takes an ARG and a precision, checks if the counterexample in + * the ARG is feasible and if not, it refines the precision and may also prune the ARG. + */ +public interface ArgRefiner extends Refiner, Trace> { +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicAbstractor.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java similarity index 91% rename from subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicAbstractor.java rename to subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java index 42eb1487e1..050ae32ce3 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicAbstractor.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java @@ -41,7 +41,7 @@ /** * Basic implementation for the abstractor, relying on an ArgBuilder. */ -public class BasicAbstractor implements Abstractor { +public class BasicArgAbstractor implements ArgAbstractor { protected final ArgBuilder argBuilder; protected final Function projection; @@ -49,8 +49,8 @@ public class BasicAbstractor protected final StopCriterion stopCriterion; protected final Logger logger; - protected BasicAbstractor(final ArgBuilder argBuilder, final Function projection, - final Waitlist> waitlist, final StopCriterion stopCriterion, final Logger logger) { + protected BasicArgAbstractor(final ArgBuilder argBuilder, final Function projection, + final Waitlist> waitlist, final StopCriterion stopCriterion, final Logger logger) { this.argBuilder = checkNotNull(argBuilder); this.projection = checkNotNull(projection); this.waitlist = checkNotNull(waitlist); @@ -64,7 +64,7 @@ public static Builder createArg() { + public ARG createWitness() { return argBuilder.createArg(); } @@ -174,8 +174,8 @@ public Builder logger(final Logger logger) { return this; } - public BasicAbstractor build() { - return new BasicAbstractor<>(argBuilder, projection, waitlist, stopCriterion, logger); + public BasicArgAbstractor build() { + return new BasicArgAbstractor<>(argBuilder, projection, waitlist, stopCriterion, logger); } } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java index af69cd7121..fa811afc42 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java @@ -17,19 +17,18 @@ import com.google.common.base.Stopwatch; import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.State; -import hu.bme.mit.theta.analysis.Trace; -import hu.bme.mit.theta.analysis.algorithm.SafetyResult; -import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; +import hu.bme.mit.theta.analysis.algorithm.SafetyResult; +import hu.bme.mit.theta.analysis.algorithm.Witness; import hu.bme.mit.theta.analysis.runtimemonitor.MonitorCheckpoint; -import hu.bme.mit.theta.analysis.utils.ArgVisualizer; +import hu.bme.mit.theta.analysis.utils.WitnessVisualizer; import hu.bme.mit.theta.common.Utils; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; import hu.bme.mit.theta.common.logging.NullLogger; - import hu.bme.mit.theta.common.visualization.writer.JSONWriter; import hu.bme.mit.theta.common.visualization.writer.WebDebuggerLogger; @@ -43,42 +42,44 @@ * check counterexamples and refine them if needed. It also provides certain * statistics about its execution. */ -public final class CegarChecker implements SafetyChecker, Trace, P> { +public final class CegarChecker implements SafetyChecker { - private final Abstractor abstractor; - private final Refiner refiner; + private final Abstractor abstractor; + private final Refiner refiner; private final Logger logger; - private final ARG arg; // TODO I don't think putting the ARG up here from check below causes any issues, but keep it in mind, that it might + private final W witness; + private final WitnessVisualizer witnessVisualizer; - private CegarChecker(final Abstractor abstractor, final Refiner refiner, final Logger logger) { + private CegarChecker(final Abstractor abstractor, final Refiner refiner, final Logger logger, final WitnessVisualizer witnessVisualizer) { this.abstractor = checkNotNull(abstractor); this.refiner = checkNotNull(refiner); this.logger = checkNotNull(logger); - arg = abstractor.createArg(); + witness = abstractor.createWitness(); + this.witnessVisualizer = checkNotNull(witnessVisualizer); } - public static CegarChecker create( - final Abstractor abstractor, final Refiner refiner) { - return new CegarChecker<>(abstractor, refiner, NullLogger.getInstance()); + public static CegarChecker create( + final Abstractor abstractor, final Refiner refiner, final WitnessVisualizer witnessVisualizer) { + return create(abstractor, refiner, NullLogger.getInstance(), witnessVisualizer); } - public static CegarChecker create( - final Abstractor abstractor, final Refiner refiner, final Logger logger) { - return new CegarChecker<>(abstractor, refiner, logger); + public static CegarChecker create( + final Abstractor abstractor, final Refiner refiner, final Logger logger, final WitnessVisualizer witnessVisualizer) { + return new CegarChecker<>(abstractor, refiner, logger, witnessVisualizer); } - public ARG getArg() { - return arg; + public W getWitness() { + return witness; } @Override - public SafetyResult, Trace> check(final P initPrec) { + public SafetyResult check(final P initPrec) { logger.write(Level.INFO, "Configuration: %s%n", this); final Stopwatch stopwatch = Stopwatch.createStarted(); long abstractorTime = 0; long refinerTime = 0; - RefinerResult refinerResult = null; - AbstractorResult abstractorResult = null; + RefinerResult refinerResult = null; + AbstractorResult abstractorResult; P prec = initPrec; int iteration = 0; WebDebuggerLogger wdl = WebDebuggerLogger.getInstance(); @@ -88,12 +89,12 @@ public SafetyResult, Trace> check(final P initPrec) { logger.write(Level.MAINSTEP, "Iteration %d%n", iteration); logger.write(Level.MAINSTEP, "| Checking abstraction...%n"); final long abstractorStartTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); - abstractorResult = abstractor.check(arg, prec); + abstractorResult = abstractor.check(witness, prec); abstractorTime += stopwatch.elapsed(TimeUnit.MILLISECONDS) - abstractorStartTime; logger.write(Level.MAINSTEP, "| Checking abstraction done, result: %s%n", abstractorResult); if (WebDebuggerLogger.enabled()) { - String argGraph = JSONWriter.getInstance().writeString(ArgVisualizer.getDefault().visualize(arg)); + String argGraph = JSONWriter.getInstance().writeString(witnessVisualizer.visualize(witness)); String precString = prec.toString(); wdl.addIteration(iteration, argGraph, precString); } @@ -104,7 +105,7 @@ public SafetyResult, Trace> check(final P initPrec) { P lastPrec = prec; logger.write(Level.MAINSTEP, "| Refining abstraction...%n"); final long refinerStartTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); - refinerResult = refiner.refine(arg, prec); + refinerResult = refiner.refine(witness, prec); refinerTime += stopwatch.elapsed(TimeUnit.MILLISECONDS) - refinerStartTime; logger.write(Level.MAINSTEP, "Refining abstraction done, result: %s%n", refinerResult); @@ -123,16 +124,16 @@ public SafetyResult, Trace> check(final P initPrec) { } while (!abstractorResult.isSafe() && !refinerResult.isUnsafe()); stopwatch.stop(); - SafetyResult, Trace> cegarResult = null; + SafetyResult cegarResult = null; final CegarStatistics stats = new CegarStatistics(stopwatch.elapsed(TimeUnit.MILLISECONDS), abstractorTime, refinerTime, iteration); - assert abstractorResult.isSafe() || (refinerResult != null && refinerResult.isUnsafe()); + assert abstractorResult.isSafe() || refinerResult.isUnsafe(); if (abstractorResult.isSafe()) { - cegarResult = SafetyResult.safe(arg, stats); + cegarResult = SafetyResult.safe(witness, stats); } else if (refinerResult.isUnsafe()) { - cegarResult = SafetyResult.unsafe(refinerResult.asUnsafe().getCex(), arg, stats); + cegarResult = SafetyResult.unsafe(refinerResult.asUnsafe().getCex(), witness, stats); } assert cegarResult != null; diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java index 0bbfe07f1d..6eca5d7c21 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java @@ -16,23 +16,19 @@ package hu.bme.mit.theta.analysis.algorithm.cegar; import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.State; -import hu.bme.mit.theta.analysis.algorithm.arg.ARG; +import hu.bme.mit.theta.analysis.algorithm.Witness; /** - * Common interface for refiners. It takes an ARG and a precision, checks if the counterexample in - * the ARG is feasible and if not, it refines the precision and may also prune the ARG. + * Common interface for refiners. It takes a witness and a precision, checks if the counterexample in + * the witness is feasible and if not, it refines the precision */ -public interface Refiner { +public interface Refiner { /** - * Checks if the counterexample in the ARG is feasible. If not, refines the precision and prunes - * the ARG. - * - * @param arg - * @param prec - * @return + * Checks if the counterexample in the witness is feasible. If not, refines the precision */ - RefinerResult refine(ARG arg, P prec); + RefinerResult refine(W witness, P prec); } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java index bbce8b5451..a4be30781e 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java @@ -15,30 +15,29 @@ */ package hu.bme.mit.theta.analysis.algorithm.cegar; -import static com.google.common.base.Preconditions.checkNotNull; - import hu.bme.mit.theta.analysis.Action; +import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.State; -import hu.bme.mit.theta.analysis.Trace; import hu.bme.mit.theta.common.Utils; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Represents the result of the Refiner class that can be either spurious or unsafe. In the former * case it also contains the refined precision and in the latter case the feasible counterexample. */ -public abstract class RefinerResult { +public abstract class RefinerResult { - private RefinerResult() { + protected RefinerResult() { } /** * Create a new spurious result. * * @param refinedPrec Refined precision - * @return */ - public static Spurious spurious( + public static Spurious spurious( final P refinedPrec) { return new Spurious<>(refinedPrec); } @@ -47,10 +46,9 @@ public static Spurious Unsafe unsafe( - final Trace cex) { + public static Unsafe unsafe( + final C cex) { return new Unsafe<>(cex); } @@ -58,15 +56,15 @@ public static Unsafe asSpurious(); + public abstract Spurious asSpurious(); - public abstract Unsafe asUnsafe(); + public abstract Unsafe asUnsafe(); /** * Represents the spurious result with a refined precision. */ - public static final class Spurious - extends RefinerResult { + public static final class Spurious + extends RefinerResult { private final P refinedPrec; @@ -89,12 +87,12 @@ public boolean isUnsafe() { } @Override - public Spurious asSpurious() { + public Spurious asSpurious() { return this; } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { throw new ClassCastException( "Cannot cast " + Spurious.class.getSimpleName() + " to " + Unsafe.class.getSimpleName()); @@ -111,16 +109,16 @@ public String toString() { /** * Represents the unsafe result with a feasible counterexample. */ - public static final class Unsafe extends - RefinerResult { + public static final class Unsafe extends + RefinerResult { - private final Trace cex; + private final C cex; - private Unsafe(final Trace cex) { + private Unsafe(final C cex) { this.cex = checkNotNull(cex); } - public Trace getCex() { + public C getCex() { return cex; } @@ -135,14 +133,14 @@ public boolean isUnsafe() { } @Override - public Spurious asSpurious() { + public Spurious asSpurious() { throw new ClassCastException( "Cannot cast " + Unsafe.class.getSimpleName() + " to " + Spurious.class.getSimpleName()); } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { return this; } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java index 8f2f499547..f1f7430241 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java @@ -16,9 +16,10 @@ package hu.bme.mit.theta.analysis.expr.refinement; import hu.bme.mit.theta.analysis.Prec; +import hu.bme.mit.theta.analysis.Trace; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode; -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner; import hu.bme.mit.theta.analysis.algorithm.cegar.RefinerResult; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; @@ -29,15 +30,15 @@ import java.util.Set; import java.util.stream.Collectors; -public final class AasporRefiner implements Refiner { +public final class AasporRefiner implements ArgRefiner { - private final Refiner refiner; + private final ArgRefiner refiner; private final PruneStrategy pruneStrategy; private final Map, Set> ignoredVarRegistry; - private AasporRefiner(final Refiner refiner, + private AasporRefiner(final ArgRefiner refiner, final PruneStrategy pruneStrategy, final Map, Set> ignoredVarRegistry) { this.refiner = refiner; @@ -46,14 +47,14 @@ private AasporRefiner(final Refiner refiner, } public static AasporRefiner create( - final Refiner refiner, final PruneStrategy pruneStrategy, + final ArgRefiner refiner, final PruneStrategy pruneStrategy, final Map, Set> ignoredVarRegistry) { return new AasporRefiner<>(refiner, pruneStrategy, ignoredVarRegistry); } @Override - public RefinerResult refine(final ARG arg, final P prec) { - final RefinerResult result = refiner.refine(arg, prec); + public RefinerResult> refine(final ARG arg, final P prec) { + final RefinerResult> result = refiner.refine(arg, prec); if (result.isUnsafe() || pruneStrategy != PruneStrategy.LAZY) return result; final P newPrec = result.asSpurious().getRefinedPrec(); diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java index 72c516adef..b2cee796d0 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java @@ -20,7 +20,7 @@ import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode; import hu.bme.mit.theta.analysis.algorithm.arg.ArgTrace; -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner; import hu.bme.mit.theta.analysis.algorithm.cegar.RefinerResult; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; @@ -34,7 +34,7 @@ import static com.google.common.base.Preconditions.checkNotNull; public final class MultiExprTraceRefiner - implements Refiner { + implements ArgRefiner { private final ExprTraceChecker exprTraceChecker; private final PrecRefiner precRefiner; @@ -76,17 +76,17 @@ public static refine(final ARG arg, final P prec) { + public RefinerResult> refine(final ARG arg, final P prec) { checkNotNull(arg); checkNotNull(prec); assert !arg.isSafe() : "ARG must be unsafe"; - final List> cexs = arg.getCexs().collect(Collectors.toList()); - final List> traces = arg.getCexs().map(ArgTrace::toTrace).collect(Collectors.toList()); + final List> cexs = arg.getCexs().toList(); + final List> traces = arg.getCexs().map(ArgTrace::toTrace).toList(); assert traces.size() == cexs.size(); logger.write(Level.INFO, "| | Number of traces: %d%n", traces.size()); - assert traces.size() > 0 : "No counterexample in ARG"; + assert !traces.isEmpty() : "No counterexample in ARG"; logger.write(Level.SUBSTEP, "| | Checking traces..."); final List> cexStatuses = new ArrayList<>(traces.size()); @@ -106,7 +106,7 @@ public RefinerResult refine(final ARG arg, final P prec) { assert cexStatuses.size() == cexs.size(); logger.write(Level.SUBSTEP, "done, result: all infeasible%n"); final List refutations = cexStatuses.stream().map(s -> s.asInfeasible().getRefutation()) - .collect(Collectors.toList()); + .toList(); assert refutations.size() == cexs.size(); final List> nodesToPrune = new ArrayList<>(traces.size()); @@ -120,7 +120,7 @@ public RefinerResult refine(final ARG arg, final P prec) { for (int i = 0; i < nodesToPrune.size(); ++i) { final ArgNode node = nodesToPrune.get(i); - if (node.properAncestors().anyMatch(a -> nodesToPrune.contains(a))) { + if (node.properAncestors().anyMatch(nodesToPrune::contains)) { skip.set(i, true); } } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java index ac06cf2a87..126f4212f4 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java @@ -20,7 +20,7 @@ import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode; import hu.bme.mit.theta.analysis.algorithm.arg.ArgTrace; -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner; import hu.bme.mit.theta.analysis.algorithm.cegar.RefinerResult; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; @@ -37,7 +37,7 @@ * ExprActions) using an ExprTraceChecker and a PrecRefiner. */ public class SingleExprTraceRefiner - implements Refiner { + implements ArgRefiner { protected final ExprTraceChecker exprTraceChecker; protected final PrecRefiner precRefiner; protected final PruneStrategy pruneStrategy; @@ -78,7 +78,7 @@ public static refine(final ARG arg, final P prec) { + public RefinerResult> refine(final ARG arg, final P prec) { checkNotNull(arg); checkNotNull(prec); assert !arg.isSafe() : "ARG must be unsafe"; diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java index 9992e5a3e7..c4c82eeb74 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java @@ -36,7 +36,7 @@ import hu.bme.mit.theta.common.visualization.LineStyle; import hu.bme.mit.theta.common.visualization.NodeAttributes; -public final class ArgVisualizer { +public final class ArgVisualizer implements WitnessVisualizer> { private static final LineStyle COVER_EDGE_STYLE = LineStyle.DASHED; private static final LineStyle SUCC_EDGE_STYLE = LineStyle.NORMAL; @@ -53,8 +53,8 @@ public final class ArgVisualizer { private static class LazyHolderDefault { - static final ArgVisualizer INSTANCE = new ArgVisualizer<>(s -> s.toString(), - a -> a.toString()); + static final ArgVisualizer INSTANCE = new ArgVisualizer<>(Object::toString, + Object::toString); } private static class LazyHolderStructureOnly { @@ -81,6 +81,7 @@ public static ArgVisualizer getStructureOnly() { return LazyHolderStructureOnly.INSTANCE; } + @Override public Graph visualize(final ARG arg) { final Graph graph = new Graph(ARG_ID, ARG_LABEL); diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java new file mode 100644 index 0000000000..bd1a9d8234 --- /dev/null +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package hu.bme.mit.theta.analysis.utils; + +import hu.bme.mit.theta.analysis.algorithm.Witness; +import hu.bme.mit.theta.common.visualization.Graph; + +public interface WitnessVisualizer { + + Graph visualize(W witness); + +} diff --git a/subprojects/common/analysis/src/main/kotlin/hu/bme/mit/theta/analysis/multi/config/StmtMultiConfigBuilder.kt b/subprojects/common/analysis/src/main/kotlin/hu/bme/mit/theta/analysis/multi/config/StmtMultiConfigBuilder.kt index 2e7f57a91a..e0d8173455 100644 --- a/subprojects/common/analysis/src/main/kotlin/hu/bme/mit/theta/analysis/multi/config/StmtMultiConfigBuilder.kt +++ b/subprojects/common/analysis/src/main/kotlin/hu/bme/mit/theta/analysis/multi/config/StmtMultiConfigBuilder.kt @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.analysis.multi.config import hu.bme.mit.theta.analysis.Prec import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor import hu.bme.mit.theta.analysis.expr.ExprState import hu.bme.mit.theta.analysis.expr.StmtAction import hu.bme.mit.theta.analysis.expr.refinement.* @@ -39,117 +38,264 @@ import hu.bme.mit.theta.solver.SolverFactory import hu.bme.mit.theta.solver.UCSolver import java.util.function.Predicate -sealed class StmtMultiConfigBuilder( - private val product: MultiBuilderResultPOJO, ExprMultiState, StmtMultiAction, StmtMultiLts>, - val prop: Expr, - val target: Predicate>, - private val lRefToPrec: RefutationToPrec, - private val rRefToPrec: RefutationToPrec, - private val dRefToPrec: RefutationToPrec, - private val lInitPrec: LPrec, - private val rInitPrec: RPrec, - private val dInitPrec: DataPrec, - val solverFactory: SolverFactory, - val logger: Logger, - val pruneStrategy: PruneStrategy = PruneStrategy.FULL +sealed class StmtMultiConfigBuilder< + LState : ExprState, + RState : ExprState, + DataState : ExprState, + LControl : ExprState, + RControl : ExprState, + LAction : StmtAction, + RAction : StmtAction, + R : Refutation, + LPrec : Prec, + RPrec : Prec, + DataPrec : Prec, + LControlPrec : Prec, + RControlPrec : Prec, +>( + private val product: + MultiBuilderResultPOJO< + LState, + RState, + DataState, + LControl, + RControl, + LAction, + RAction, + LPrec, + RPrec, + DataPrec, + LControlPrec, + RControlPrec, + ExprMultiState, + ExprMultiState, + StmtMultiAction, + StmtMultiLts, + >, + val prop: Expr, + val target: Predicate>, + private val lRefToPrec: RefutationToPrec, + private val rRefToPrec: RefutationToPrec, + private val dRefToPrec: RefutationToPrec, + private val lInitPrec: LPrec, + private val rInitPrec: RPrec, + private val dInitPrec: DataPrec, + val solverFactory: SolverFactory, + val logger: Logger, + val pruneStrategy: PruneStrategy = PruneStrategy.FULL, ) { - abstract fun getTraceChecker(): ExprTraceChecker + abstract fun getTraceChecker(): ExprTraceChecker - fun build(): MultiConfig, StmtMultiAction> { - val argBuilder = ArgBuilder.create(product.lts, product.side.analysis, target) - val abstractor = BasicAbstractor.builder(argBuilder).build() - val traceChecker = getTraceChecker() - val precRefiner = - JoiningPrecRefiner.create, StmtMultiAction, MultiPrec, R>( - RefToMultiPrec(lRefToPrec, rRefToPrec, dRefToPrec) - ) - val refiner = SingleExprTraceRefiner.create(traceChecker, precRefiner, pruneStrategy, logger) - return MultiConfig(CegarChecker.create(abstractor, refiner), MultiPrec(lInitPrec, rInitPrec, dInitPrec)) - } + fun build(): + MultiConfig< + DataState, + LControl, + RControl, + LAction, + RAction, + LPrec, + RPrec, + DataPrec, + ExprMultiState, + StmtMultiAction, + > { + val argBuilder = ArgBuilder.create(product.lts, product.side.analysis, target) + val abstractor = BasicArgAbstractor.builder(argBuilder).build() + val traceChecker = getTraceChecker() + val precRefiner = + JoiningPrecRefiner.create< + ExprMultiState, + StmtMultiAction, + MultiPrec, + R, + >( + RefToMultiPrec(lRefToPrec, rRefToPrec, dRefToPrec) + ) + val refiner = SingleExprTraceRefiner.create(traceChecker, precRefiner, pruneStrategy, logger) + return MultiConfig( + ArgCegarChecker.create(abstractor, refiner), + MultiPrec(lInitPrec, rInitPrec, dInitPrec), + ) + } - class ItpStmtMultiConfigBuilder( - product: MultiBuilderResultPOJO, ExprMultiState, StmtMultiAction, StmtMultiLts>, - prop: Expr, - target: Predicate>, - lRefToPrec: RefutationToPrec, - rRefToPrec: RefutationToPrec, - dRefToPrec: RefutationToPrec, - lInitPrec: LPrec, - rInitPrec: RPrec, - dInitPrec: DataPrec, - solverFactory: SolverFactory, - logger: Logger, - pruneStrategy: PruneStrategy = PruneStrategy.FULL, - private val traceCheckerType: TraceCheckerType = TraceCheckerType.SEQ_ITP - ) : StmtMultiConfigBuilder( - product, - prop, - target, - lRefToPrec, - rRefToPrec, - dRefToPrec, - lInitPrec, - rInitPrec, - dInitPrec, - solverFactory, - logger, - pruneStrategy + class ItpStmtMultiConfigBuilder< + LState : ExprState, + RState : ExprState, + DataState : ExprState, + LControl : ExprState, + RControl : ExprState, + LAction : StmtAction, + RAction : StmtAction, + LPrec : Prec, + RPrec : Prec, + DataPrec : Prec, + LControlPrec : Prec, + RControlPrec : Prec, + >( + product: + MultiBuilderResultPOJO< + LState, + RState, + DataState, + LControl, + RControl, + LAction, + RAction, + LPrec, + RPrec, + DataPrec, + LControlPrec, + RControlPrec, + ExprMultiState, + ExprMultiState, + StmtMultiAction, + StmtMultiLts, + >, + prop: Expr, + target: Predicate>, + lRefToPrec: RefutationToPrec, + rRefToPrec: RefutationToPrec, + dRefToPrec: RefutationToPrec, + lInitPrec: LPrec, + rInitPrec: RPrec, + dInitPrec: DataPrec, + solverFactory: SolverFactory, + logger: Logger, + pruneStrategy: PruneStrategy = PruneStrategy.FULL, + private val traceCheckerType: TraceCheckerType = TraceCheckerType.SEQ_ITP, + ) : + StmtMultiConfigBuilder< + LState, + RState, + DataState, + LControl, + RControl, + LAction, + RAction, + ItpRefutation, + LPrec, + RPrec, + DataPrec, + LControlPrec, + RControlPrec, + >( + product, + prop, + target, + lRefToPrec, + rRefToPrec, + dRefToPrec, + lInitPrec, + rInitPrec, + dInitPrec, + solverFactory, + logger, + pruneStrategy, ) { - enum class TraceCheckerType( - val generator: (init: Expr, target: Expr, solver: ItpSolver) -> ExprTraceChecker - ) { - - SEQ_ITP(ExprTraceSeqItpChecker::create), FW_BIN(ExprTraceFwBinItpChecker::create), BW_BIN( - ExprTraceBwBinItpChecker::create - ) - } + enum class TraceCheckerType( + val generator: + (init: Expr, target: Expr, solver: ItpSolver) -> ExprTraceChecker< + ItpRefutation + > + ) { - override fun getTraceChecker(): ExprTraceChecker = traceCheckerType.generator( - BoolExprs.True(), prop, solverFactory.createItpSolver() - ) + SEQ_ITP(ExprTraceSeqItpChecker::create), + FW_BIN(ExprTraceFwBinItpChecker::create), + BW_BIN(ExprTraceBwBinItpChecker::create), } - class VarsStmtMultiConfigBuilder( - product: MultiBuilderResultPOJO, ExprMultiState, StmtMultiAction, StmtMultiLts>, - prop: Expr, - target: Predicate>, - lRefToPrec: RefutationToPrec, - rRefToPrec: RefutationToPrec, - dRefToPrec: RefutationToPrec, - lInitPrec: LPrec, - rInitPrec: RPrec, - dInitPrec: DataPrec, - solverFactory: SolverFactory, - logger: Logger, - pruneStrategy: PruneStrategy = PruneStrategy.FULL, - private val traceCheckerType: TraceCheckerType = TraceCheckerType.UNSAT_CORE - ) : StmtMultiConfigBuilder( - product, - prop, - target, - lRefToPrec, - rRefToPrec, - dRefToPrec, - lInitPrec, - rInitPrec, - dInitPrec, - solverFactory, - logger, - pruneStrategy - ) { + override fun getTraceChecker(): ExprTraceChecker = + traceCheckerType.generator(BoolExprs.True(), prop, solverFactory.createItpSolver()) + } - enum class TraceCheckerType( - val generator: (init: Expr, target: Expr, solver: UCSolver) -> ExprTraceChecker - ) { + class VarsStmtMultiConfigBuilder< + LState : ExprState, + RState : ExprState, + DataState : ExprState, + LControl : ExprState, + RControl : ExprState, + LAction : StmtAction, + RAction : StmtAction, + LPrec : Prec, + RPrec : Prec, + DataPrec : Prec, + LControlPrec : Prec, + RControlPrec : Prec, + >( + product: + MultiBuilderResultPOJO< + LState, + RState, + DataState, + LControl, + RControl, + LAction, + RAction, + LPrec, + RPrec, + DataPrec, + LControlPrec, + RControlPrec, + ExprMultiState, + ExprMultiState, + StmtMultiAction, + StmtMultiLts, + >, + prop: Expr, + target: Predicate>, + lRefToPrec: RefutationToPrec, + rRefToPrec: RefutationToPrec, + dRefToPrec: RefutationToPrec, + lInitPrec: LPrec, + rInitPrec: RPrec, + dInitPrec: DataPrec, + solverFactory: SolverFactory, + logger: Logger, + pruneStrategy: PruneStrategy = PruneStrategy.FULL, + private val traceCheckerType: TraceCheckerType = TraceCheckerType.UNSAT_CORE, + ) : + StmtMultiConfigBuilder< + LState, + RState, + DataState, + LControl, + RControl, + LAction, + RAction, + VarsRefutation, + LPrec, + RPrec, + DataPrec, + LControlPrec, + RControlPrec, + >( + product, + prop, + target, + lRefToPrec, + rRefToPrec, + dRefToPrec, + lInitPrec, + rInitPrec, + dInitPrec, + solverFactory, + logger, + pruneStrategy, + ) { - UNSAT_CORE(ExprTraceUnsatCoreChecker::create) - } + enum class TraceCheckerType( + val generator: + (init: Expr, target: Expr, solver: UCSolver) -> ExprTraceChecker< + VarsRefutation + > + ) { - override fun getTraceChecker(): ExprTraceChecker = traceCheckerType.generator( - BoolExprs.True(), prop, solverFactory.createUCSolver() - ) + UNSAT_CORE(ExprTraceUnsatCoreChecker::create) } + override fun getTraceChecker(): ExprTraceChecker = + traceCheckerType.generator(BoolExprs.True(), prop, solverFactory.createUCSolver()) + } } diff --git a/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java b/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java index 397a4a4ef8..7e946253e9 100644 --- a/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java +++ b/subprojects/sts/sts-analysis/src/main/java/hu/bme/mit/theta/sts/analysis/config/StsConfigBuilder.java @@ -15,16 +15,18 @@ */ package hu.bme.mit.theta.sts.analysis.config; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; + import hu.bme.mit.theta.analysis.*; +import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators.ArgNodeComparator; -import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions; import hu.bme.mit.theta.analysis.expl.ExplAnalysis; import hu.bme.mit.theta.analysis.expl.ExplPrec; @@ -66,19 +68,23 @@ import hu.bme.mit.theta.sts.analysis.initprec.StsEmptyInitPrec; import hu.bme.mit.theta.sts.analysis.initprec.StsInitPrec; import hu.bme.mit.theta.sts.analysis.initprec.StsPropInitPrec; - import java.util.function.Predicate; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; - public final class StsConfigBuilder { public enum Domain { - EXPL, PRED_BOOL, PRED_CART, PRED_SPLIT + EXPL, + PRED_BOOL, + PRED_CART, + PRED_SPLIT } public enum Refinement { - FW_BIN_ITP, BW_BIN_ITP, SEQ_ITP, MULTI_SEQ, UNSAT_CORE + FW_BIN_ITP, + BW_BIN_ITP, + SEQ_ITP, + MULTI_SEQ, + UNSAT_CORE } public enum Search { @@ -91,7 +97,6 @@ public enum Search { private Search(final ArgNodeComparator comparator) { this.comparator = comparator; } - } public enum PredSplit { @@ -109,14 +114,14 @@ private PredSplit(final ExprSplitter splitter) { } public enum InitPrec { - EMPTY(new StsEmptyInitPrec()), PROP(new StsPropInitPrec()); + EMPTY(new StsEmptyInitPrec()), + PROP(new StsPropInitPrec()); public final StsInitPrec builder; private InitPrec(final StsInitPrec builder) { this.builder = builder; } - } private Logger logger = NullLogger.getInstance(); @@ -128,8 +133,8 @@ private InitPrec(final StsInitPrec builder) { private InitPrec initPrec = InitPrec.EMPTY; private PruneStrategy pruneStrategy = PruneStrategy.LAZY; - public StsConfigBuilder(final Domain domain, final Refinement refinement, - final SolverFactory solverFactory) { + public StsConfigBuilder( + final Domain domain, final Refinement refinement, final SolverFactory solverFactory) { this.domain = domain; this.refinement = refinement; this.solverFactory = solverFactory; @@ -168,63 +173,80 @@ public StsConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { if (domain == Domain.EXPL) { final Solver analysisSolver = solverFactory.createSolver(); final Predicate target = new ExplStatePredicate(negProp, analysisSolver); - final Analysis analysis = ExplAnalysis.create( - analysisSolver, init); - final ArgBuilder argBuilder = ArgBuilder.create(lts, - analysis, target, - true); - final Abstractor abstractor = BasicAbstractor.builder( - argBuilder) - .waitlist(PriorityWaitlist.create(search.comparator)) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()) - .logger(logger).build(); - - Refiner refiner = null; + final Analysis analysis = + ExplAnalysis.create(analysisSolver, init); + final ArgBuilder argBuilder = + ArgBuilder.create(lts, analysis, target, true); + final ArgAbstractor abstractor = + BasicArgAbstractor.builder(argBuilder) + .waitlist(PriorityWaitlist.create(search.comparator)) + .stopCriterion( + refinement == Refinement.MULTI_SEQ + ? StopCriterions.fullExploration() + : StopCriterions.firstCex()) + .logger(logger) + .build(); + + ArgRefiner refiner = null; switch (refinement) { case FW_BIN_ITP: - refiner = SingleExprTraceRefiner.create( - ExprTraceFwBinItpChecker.create(init, negProp, - solverFactory.createItpSolver()), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = + SingleExprTraceRefiner.create( + ExprTraceFwBinItpChecker.create( + init, negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), + pruneStrategy, + logger); break; case BW_BIN_ITP: - refiner = SingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(init, negProp, - solverFactory.createItpSolver()), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = + SingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + init, negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), + pruneStrategy, + logger); break; case SEQ_ITP: - refiner = SingleExprTraceRefiner.create( - ExprTraceSeqItpChecker.create(init, negProp, - solverFactory.createItpSolver()), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = + SingleExprTraceRefiner.create( + ExprTraceSeqItpChecker.create( + init, negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), + pruneStrategy, + logger); break; case MULTI_SEQ: - refiner = MultiExprTraceRefiner.create( - ExprTraceSeqItpChecker.create(init, negProp, - solverFactory.createItpSolver()), - JoiningPrecRefiner.create(new ItpRefToExplPrec()), pruneStrategy, logger); + refiner = + MultiExprTraceRefiner.create( + ExprTraceSeqItpChecker.create( + init, negProp, solverFactory.createItpSolver()), + JoiningPrecRefiner.create(new ItpRefToExplPrec()), + pruneStrategy, + logger); break; case UNSAT_CORE: - refiner = SingleExprTraceRefiner.create( - ExprTraceUnsatCoreChecker.create(init, negProp, - solverFactory.createUCSolver()), - JoiningPrecRefiner.create(new VarsRefToExplPrec()), pruneStrategy, logger); + refiner = + SingleExprTraceRefiner.create( + ExprTraceUnsatCoreChecker.create( + init, negProp, solverFactory.createUCSolver()), + JoiningPrecRefiner.create(new VarsRefToExplPrec()), + pruneStrategy, + logger); break; default: throw new UnsupportedOperationException( domain + " domain does not support " + refinement + " refinement."); } - final SafetyChecker, Trace, ExplPrec> checker = CegarChecker.create( - abstractor, refiner, - logger); + final SafetyChecker, Trace, ExplPrec> + checker = ArgCegarChecker.create(abstractor, refiner, logger); final ExplPrec prec = initPrec.builder.createExpl(sts); return StsConfig.create(checker, prec); - } else if (domain == Domain.PRED_BOOL || domain == Domain.PRED_CART + } else if (domain == Domain.PRED_BOOL + || domain == Domain.PRED_CART || domain == Domain.PRED_SPLIT) { final Solver analysisSolver = solverFactory.createSolver(); PredAbstractor predAbstractor = null; @@ -242,55 +264,65 @@ public StsConfigBuilder pruneStrategy(final PruneStrategy pruneStrategy) { throw new UnsupportedOperationException(domain + " domain is not supported."); } final Predicate target = new ExprStatePredicate(negProp, analysisSolver); - final Analysis analysis = PredAnalysis.create( - analysisSolver, predAbstractor, - init); - final ArgBuilder argBuilder = ArgBuilder.create(lts, - analysis, target, - true); - final Abstractor abstractor = BasicAbstractor.builder( - argBuilder) - .waitlist(PriorityWaitlist.create(search.comparator)) - .stopCriterion(refinement == Refinement.MULTI_SEQ ? StopCriterions.fullExploration() - : StopCriterions.firstCex()) - .logger(logger).build(); + final Analysis analysis = + PredAnalysis.create(analysisSolver, predAbstractor, init); + final ArgBuilder argBuilder = + ArgBuilder.create(lts, analysis, target, true); + final ArgAbstractor abstractor = + BasicArgAbstractor.builder(argBuilder) + .waitlist(PriorityWaitlist.create(search.comparator)) + .stopCriterion( + refinement == Refinement.MULTI_SEQ + ? StopCriterions.fullExploration() + : StopCriterions.firstCex()) + .logger(logger) + .build(); ExprTraceChecker exprTraceChecker = null; switch (refinement) { case FW_BIN_ITP: - exprTraceChecker = ExprTraceFwBinItpChecker.create(init, negProp, - solverFactory.createItpSolver()); + exprTraceChecker = + ExprTraceFwBinItpChecker.create( + init, negProp, solverFactory.createItpSolver()); break; case BW_BIN_ITP: - exprTraceChecker = ExprTraceBwBinItpChecker.create(init, negProp, - solverFactory.createItpSolver()); + exprTraceChecker = + ExprTraceBwBinItpChecker.create( + init, negProp, solverFactory.createItpSolver()); break; case SEQ_ITP: - exprTraceChecker = ExprTraceSeqItpChecker.create(init, negProp, - solverFactory.createItpSolver()); + exprTraceChecker = + ExprTraceSeqItpChecker.create( + init, negProp, solverFactory.createItpSolver()); break; case MULTI_SEQ: - exprTraceChecker = ExprTraceSeqItpChecker.create(init, negProp, - solverFactory.createItpSolver()); + exprTraceChecker = + ExprTraceSeqItpChecker.create( + init, negProp, solverFactory.createItpSolver()); break; default: throw new UnsupportedOperationException( domain + " domain does not support " + refinement + " refinement."); } - Refiner refiner; + ArgRefiner refiner; if (refinement == Refinement.MULTI_SEQ) { - refiner = MultiExprTraceRefiner.create(exprTraceChecker, - JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), - pruneStrategy, logger); + refiner = + MultiExprTraceRefiner.create( + exprTraceChecker, + JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), + pruneStrategy, + logger); } else { - refiner = SingleExprTraceRefiner.create(exprTraceChecker, - JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), - pruneStrategy, logger); + refiner = + SingleExprTraceRefiner.create( + exprTraceChecker, + JoiningPrecRefiner.create(new ItpRefToPredPrec(predSplit.splitter)), + pruneStrategy, + logger); } - final SafetyChecker, Trace, PredPrec> checker = CegarChecker.create( - abstractor, refiner, - logger); + final SafetyChecker, Trace, PredPrec> + checker = ArgCegarChecker.create(abstractor, refiner, logger); final PredPrec prec = initPrec.builder.createPred(sts); return StsConfig.create(checker, prec); diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java index db171f2718..4f2f998af5 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java @@ -24,9 +24,9 @@ import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; import hu.bme.mit.theta.analysis.expl.ExplAnalysis; import hu.bme.mit.theta.analysis.expl.ExplPrec; import hu.bme.mit.theta.analysis.expl.ExplState; @@ -110,7 +110,7 @@ public void test() { final ArgBuilder argBuilder = ArgBuilder.create(lts, analysis, target); - final Abstractor abstractor = BasicAbstractor.builder( + final ArgAbstractor abstractor = BasicArgAbstractor.builder( argBuilder) .waitlist(PriorityWaitlist.create(ArgNodeComparators.bfs())).logger(logger).build(); @@ -122,7 +122,7 @@ public void test() { .create(exprTraceChecker, JoiningPrecRefiner.create(new VarsRefToExplPrec()), PruneStrategy.LAZY, logger); - final SafetyChecker, Trace, ExplPrec> checker = CegarChecker.create( + final SafetyChecker, Trace, ExplPrec> checker = ArgCegarChecker.create( abstractor, refiner, logger); final SafetyResult, Trace> safetyStatus = checker.check(prec); diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java index 5eea722540..bed9497f54 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java @@ -44,9 +44,9 @@ import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.analysis.expr.ExprStatePredicate; @@ -104,7 +104,7 @@ public void testPredPrec() { final ArgBuilder argBuilder = ArgBuilder.create(lts, analysis, target); - final Abstractor abstractor = BasicAbstractor.builder( + final ArgAbstractor abstractor = BasicArgAbstractor.builder( argBuilder).logger(logger) .build(); @@ -117,7 +117,7 @@ public void testPredPrec() { JoiningPrecRefiner.create(new ItpRefToPredPrec(ExprSplitters.atoms())), PruneStrategy.LAZY, logger); - final SafetyChecker, Trace, PredPrec> checker = CegarChecker.create( + final SafetyChecker, Trace, PredPrec> checker = ArgCegarChecker.create( abstractor, refiner, logger); final SafetyResult, Trace> safetyStatus = checker.check(prec); diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAbstractor.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAbstractor.kt deleted file mode 100644 index d17f15fda1..0000000000 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAbstractor.kt +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2024 Budapest University of Technology and Economics - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package hu.bme.mit.theta.xcfa.analysis - -import com.google.common.base.Preconditions -import hu.bme.mit.theta.analysis.Action -import hu.bme.mit.theta.analysis.Prec -import hu.bme.mit.theta.analysis.State -import hu.bme.mit.theta.analysis.algorithm.arg.ARG -import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder -import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode -import hu.bme.mit.theta.analysis.algorithm.cegar.AbstractorResult -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor -import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterion -import hu.bme.mit.theta.analysis.reachedset.Partition -import hu.bme.mit.theta.analysis.waitlist.Waitlist -import hu.bme.mit.theta.common.logging.Logger -import java.util.function.Function - -class XcfaAbstractor( - argBuilder: ArgBuilder, - projection: Function?, - waitlist: Waitlist>, - stopCriterion: StopCriterion, - logger: Logger, -) : BasicAbstractor(argBuilder, projection, waitlist, stopCriterion, logger) { - - override fun check(arg: ARG, prec: P): AbstractorResult { - logger.write(Logger.Level.DETAIL, "| | Precision: %s%n", prec) - - if (!arg.isInitialized) { - logger.write(Logger.Level.SUBSTEP, "| | (Re)initializing ARG...") - argBuilder.init(arg, prec) - logger.write(Logger.Level.SUBSTEP, "done%n") - } - - assert(arg.isInitialized) - - logger.write( - Logger.Level.INFO, "| | Starting ARG: %d nodes, %d incomplete, %d unsafe%n", arg.nodes.count(), - arg.incompleteNodes.count(), arg.unsafeNodes.count() - ) - logger.write(Logger.Level.SUBSTEP, "| | Building ARG...") - - val reachedSet: Partition, *> = Partition.of { n: ArgNode -> - projection.apply(n.state) - } - waitlist.clear() - - reachedSet.addAll(arg.nodes) - waitlist.addAll(arg.incompleteNodes) - - if (!stopCriterion.canStop(arg)) { - while (!waitlist.isEmpty) { - val node = waitlist.remove() - var newNodes: Collection>? = emptyList() - if ((node.state as XcfaState<*>).xcfa!!.isInlined) { - close(node, reachedSet[node]) - } else { - val expandProcedureCall = (node.state as XcfaState<*>) in (prec as XcfaPrec

).noPop - closePop(node, reachedSet[node], !expandProcedureCall) - } - if (!node.isSubsumed && !node.isTarget) { - newNodes = argBuilder.expand(node, prec) - reachedSet.addAll(newNodes) - waitlist.addAll(newNodes) - } - if (stopCriterion.canStop(arg, newNodes)) break - } - } - - logger.write(Logger.Level.SUBSTEP, "done%n") - logger.write( - Logger.Level.INFO, "| | Finished ARG: %d nodes, %d incomplete, %d unsafe%n", arg.nodes.count(), - arg.incompleteNodes.count(), arg.unsafeNodes.count() - ) - - waitlist.clear() // Optimization - - return if (arg.isSafe) { - Preconditions.checkState(arg.isComplete, "Returning incomplete ARG as safe") - AbstractorResult.safe() - } else { - AbstractorResult.unsafe() - } - } - - fun closePop(node: ArgNode, candidates: Collection>, popCovered: Boolean) { - if (!node.isLeaf) { - return - } - for (candidate in candidates) { - if (candidate.mayCover(node)) { - var onlyStackCovers = false - (node.state as XcfaState<*>).processes.forEach { (pid: Int, proc: XcfaProcessState) -> - if (proc != (candidate.state as XcfaState<*>).processes[pid]) { - if (popCovered) proc.popped = proc.locs.pop() - onlyStackCovers = true - } - } - if (!onlyStackCovers) { - node.cover(candidate) - } - return - } - } - } - - companion object { - - fun builder( - argBuilder: ArgBuilder): BasicAbstractor.Builder { - return Builder(argBuilder) - } - } - - class Builder(argBuilder: ArgBuilder) - : BasicAbstractor.Builder(argBuilder) { - - override fun build(): BasicAbstractor { - return XcfaAbstractor(argBuilder, projection, waitlist, stopCriterion, logger) - } - } -} diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt index 64bd2e3d62..f923d0e6f0 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.analysis import hu.bme.mit.theta.analysis.* import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterion import hu.bme.mit.theta.analysis.expl.ExplInitFunc import hu.bme.mit.theta.analysis.expl.ExplPrec @@ -54,251 +53,364 @@ import java.util.* import java.util.function.Predicate open class XcfaAnalysis( - private val corePartialOrd: PartialOrd>>, - private val coreInitFunc: InitFunc>, XcfaPrec

>, - private var coreTransFunc: TransFunc>, XcfaAction, XcfaPrec

>, + private val corePartialOrd: PartialOrd>>, + private val coreInitFunc: InitFunc>, XcfaPrec

>, + private var coreTransFunc: TransFunc>, XcfaAction, XcfaPrec

>, ) : Analysis>, XcfaAction, XcfaPrec

> { - init { - ConeOfInfluence.coreTransFunc = transFunc as TransFunc>, XcfaAction, XcfaPrec> - coreTransFunc = ConeOfInfluence.transFunc as TransFunc>, XcfaAction, XcfaPrec

> - } + init { + ConeOfInfluence.coreTransFunc = + transFunc as TransFunc>, XcfaAction, XcfaPrec> + coreTransFunc = + ConeOfInfluence.transFunc as TransFunc>, XcfaAction, XcfaPrec

> + } + + override fun getPartialOrd(): PartialOrd>> = corePartialOrd + + override fun getInitFunc(): InitFunc>, XcfaPrec

> = coreInitFunc - override fun getPartialOrd(): PartialOrd>> = corePartialOrd - override fun getInitFunc(): InitFunc>, XcfaPrec

> = coreInitFunc - override fun getTransFunc(): TransFunc>, XcfaAction, XcfaPrec

> = coreTransFunc + override fun getTransFunc(): TransFunc>, XcfaAction, XcfaPrec

> = + coreTransFunc } /// Common private var tempCnt: Int = 0 -fun getCoreXcfaLts() = LTS>, XcfaAction> { s -> - s.processes.map { proc -> + +fun getCoreXcfaLts() = + LTS>, XcfaAction> { s -> + s.processes + .map { proc -> if (proc.value.locs.peek().final) { - listOf(XcfaAction(proc.key, - XcfaEdge(proc.value.locs.peek(), proc.value.locs.peek(), SequenceLabel(listOf( + listOf( + XcfaAction( + proc.key, + XcfaEdge( + proc.value.locs.peek(), + proc.value.locs.peek(), + SequenceLabel( + listOf( proc.value.paramStmts.peek().second, ReturnLabel(proc.value.returnStmts.peek()), - ))), nextCnt = s.sGlobal.nextCnt)) + ) + ), + ), + nextCnt = s.sGlobal.nextCnt, + ) + ) } else if (!proc.value.paramsInitialized) { - listOf(XcfaAction(proc.key, XcfaEdge(proc.value.locs.peek(), proc.value.locs.peek(), - proc.value.paramStmts.peek().first), nextCnt = s.sGlobal.nextCnt)) + listOf( + XcfaAction( + proc.key, + XcfaEdge( + proc.value.locs.peek(), + proc.value.locs.peek(), + proc.value.paramStmts.peek().first, + ), + nextCnt = s.sGlobal.nextCnt, + ) + ) } else { - proc.value.locs.peek().outgoingEdges.map { edge -> - val newLabel = edge.label.changeVars(proc.value.varLookup.peek()) - val flatLabels = newLabel.getFlatLabels() - if (flatLabels.any { it is InvokeLabel || it is StartLabel }) { - val newNewLabel = SequenceLabel(flatLabels.map { label -> - if (label is InvokeLabel) { - val procedure = s.xcfa?.procedures?.find { proc -> proc.name == label.name } - ?: error("No such method ${label.name}.") - val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() - SequenceLabel(listOf(procedure.params.withIndex() - .filter { it.value.second != ParamDirection.OUT }.map { iVal -> - val originalVar = iVal.value.first - val tempVar = Var("tmp${tempCnt++}_" + originalVar.name, - originalVar.type) - lookup[originalVar] = tempVar + proc.value.locs.peek().outgoingEdges.map { edge -> + val newLabel = edge.label.changeVars(proc.value.varLookup.peek()) + val flatLabels = newLabel.getFlatLabels() + if (flatLabels.any { it is InvokeLabel || it is StartLabel }) { + val newNewLabel = + SequenceLabel( + flatLabels.map { label -> + if (label is InvokeLabel) { + val procedure = + s.xcfa?.procedures?.find { proc -> proc.name == label.name } + ?: error("No such method ${label.name}.") + val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() + SequenceLabel( + listOf( + procedure.params + .withIndex() + .filter { it.value.second != ParamDirection.OUT } + .map { iVal -> + val originalVar = iVal.value.first + val tempVar = + Var("tmp${tempCnt++}_" + originalVar.name, originalVar.type) + lookup[originalVar] = tempVar + StmtLabel( + Stmts.Assign( + TypeUtils.cast(tempVar, tempVar.type), + TypeUtils.cast(label.params[iVal.index], tempVar.type), + ), + metadata = label.metadata, + ) + }, + listOf(label.copy(tempLookup = lookup)), + ) + .flatten() + ) + } else if (label is StartLabel) { + val procedure = + s.xcfa?.procedures?.find { proc -> proc.name == label.name } + ?: error("No such method ${label.name}.") + val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() + SequenceLabel( + listOf( + procedure.params + .withIndex() + .filter { it.value.second != ParamDirection.OUT } + .mapNotNull { iVal -> + val originalVar = iVal.value.first + val tempVar = + Var("tmp${tempCnt++}_" + originalVar.name, originalVar.type) + lookup[originalVar] = tempVar + val trial = + Try.attempt { StmtLabel( - Stmts.Assign( - TypeUtils.cast(tempVar, tempVar.type), - TypeUtils.cast(label.params[iVal.index], tempVar.type)), - metadata = label.metadata) - }, listOf(label.copy(tempLookup = lookup))).flatten()) - } else if (label is StartLabel) { - val procedure = s.xcfa?.procedures?.find { proc -> proc.name == label.name } - ?: error("No such method ${label.name}.") - val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() - SequenceLabel(listOf(procedure.params.withIndex() - .filter { it.value.second != ParamDirection.OUT }.mapNotNull { iVal -> - val originalVar = iVal.value.first - val tempVar = Var("tmp${tempCnt++}_" + originalVar.name, - originalVar.type) - lookup[originalVar] = tempVar - val trial = Try.attempt { - StmtLabel( - Stmts.Assign( - TypeUtils.cast(tempVar, tempVar.type), - TypeUtils.cast(label.params[iVal.index], tempVar.type)), - metadata = label.metadata) - } - if (trial.isSuccess) { - trial.asSuccess().value - } else { - null - } - }, listOf(label.copy(tempLookup = lookup))).flatten()) - } else label - }) - XcfaAction(proc.key, edge.withLabel(newNewLabel), nextCnt = s.sGlobal.nextCnt) - } else - XcfaAction(proc.key, edge.withLabel(newLabel), nextCnt = s.sGlobal.nextCnt) - } + Stmts.Assign( + TypeUtils.cast(tempVar, tempVar.type), + TypeUtils.cast(label.params[iVal.index], tempVar.type), + ), + metadata = label.metadata, + ) + } + if (trial.isSuccess) { + trial.asSuccess().value + } else { + null + } + }, + listOf(label.copy(tempLookup = lookup)), + ) + .flatten() + ) + } else label + } + ) + XcfaAction(proc.key, edge.withLabel(newNewLabel), nextCnt = s.sGlobal.nextCnt) + } else XcfaAction(proc.key, edge.withLabel(newLabel), nextCnt = s.sGlobal.nextCnt) + } } - }.flatten().toSet() -} + } + .flatten() + .toSet() + } fun getXcfaLts(): LTS>, XcfaAction> { - val lts = getCoreXcfaLts() - return LTS>, XcfaAction> { s -> - lts.getEnabledActionsFor(s).filter { !s.apply(it).first.bottom }.toSet() - } + val lts = getCoreXcfaLts() + return LTS>, XcfaAction> { s -> + lts.getEnabledActionsFor(s).filter { !s.apply(it).first.bottom }.toSet() + } } enum class ErrorDetection { - ERROR_LOCATION, - DATA_RACE, - OVERFLOW, - NO_ERROR + ERROR_LOCATION, + DATA_RACE, + OVERFLOW, + NO_ERROR, } fun getXcfaErrorPredicate( - errorDetection: ErrorDetection): Predicate>> = when (errorDetection) { + errorDetection: ErrorDetection +): Predicate>> = + when (errorDetection) { ErrorDetection.ERROR_LOCATION -> - Predicate>> { s -> s.processes.any { it.value.locs.peek().error } } + Predicate>> { s -> + s.processes.any { it.value.locs.peek().error } + } ErrorDetection.DATA_RACE -> { - Predicate>> { s -> - val xcfa = s.xcfa!! - for (process1 in s.processes) - for (process2 in s.processes) - if (process1.key != process2.key) - for (edge1 in process1.value.locs.peek().outgoingEdges) - for (edge2 in process2.value.locs.peek().outgoingEdges) { - val mutexes1 = s.mutexes.filterValues { it == process1.key }.keys - val mutexes2 = s.mutexes.filterValues { it == process2.key }.keys - val globalVars1 = edge1.getGlobalVarsWithNeededMutexes(xcfa, mutexes1) - val globalVars2 = edge2.getGlobalVarsWithNeededMutexes(xcfa, mutexes2) - for (v1 in globalVars1) - for (v2 in globalVars2) - if (v1.varDecl == v2.varDecl) - if (v1.access.isWritten || v2.access.isWritten) - if ((v1.mutexes intersect v2.mutexes).isEmpty()) - return@Predicate true - } - false - } + Predicate>> { s -> + val xcfa = s.xcfa!! + for (process1 in s.processes) for (process2 in s.processes) if ( + process1.key != process2.key + ) + for (edge1 in process1.value.locs.peek().outgoingEdges) for (edge2 in + process2.value.locs.peek().outgoingEdges) { + val mutexes1 = s.mutexes.filterValues { it == process1.key }.keys + val mutexes2 = s.mutexes.filterValues { it == process2.key }.keys + val globalVars1 = edge1.getGlobalVarsWithNeededMutexes(xcfa, mutexes1) + val globalVars2 = edge2.getGlobalVarsWithNeededMutexes(xcfa, mutexes2) + for (v1 in globalVars1) for (v2 in globalVars2) if (v1.varDecl == v2.varDecl) + if (v1.access.isWritten || v2.access.isWritten) + if ((v1.mutexes intersect v2.mutexes).isEmpty()) return@Predicate true + } + false + } } - ErrorDetection.NO_ERROR, ErrorDetection.OVERFLOW -> Predicate>> { false } -} + ErrorDetection.NO_ERROR, + ErrorDetection.OVERFLOW -> Predicate>> { false } + } fun getPartialOrder(partialOrd: PartialOrd>) = - PartialOrd>> { s1, s2 -> - s1.processes == s2.processes && s1.bottom == s2.bottom && s1.mutexes == s2.mutexes && partialOrd.isLeq( - s1.sGlobal, s2.sGlobal) - } + PartialOrd>> { s1, s2 -> + s1.processes == s2.processes && + s1.bottom == s2.bottom && + s1.mutexes == s2.mutexes && + partialOrd.isLeq(s1.sGlobal, s2.sGlobal) + } -private fun stackIsLeq(s1: XcfaState>, - s2: XcfaState>) = s2.processes.keys.all { pid -> +private fun stackIsLeq(s1: XcfaState>, s2: XcfaState>) = + s2.processes.keys.all { pid -> s1.processes[pid]?.let { ps1 -> - val ps2 = s2.processes.getValue(pid) - ps1.locs.peek() == ps2.locs.peek() && ps1.paramsInitialized && ps2.paramsInitialized + val ps2 = s2.processes.getValue(pid) + ps1.locs.peek() == ps2.locs.peek() && ps1.paramsInitialized && ps2.paramsInitialized } ?: false -} + } fun getStackPartialOrder(partialOrd: PartialOrd>) = - PartialOrd>> { s1, s2 -> - s1.processes.size == s2.processes.size && stackIsLeq(s1, - s2) && s1.bottom == s2.bottom && s1.mutexes == s2.mutexes - && partialOrd.isLeq(s1.withGeneralizedVars(), s2.withGeneralizedVars()) - } + PartialOrd>> { s1, s2 -> + s1.processes.size == s2.processes.size && + stackIsLeq(s1, s2) && + s1.bottom == s2.bottom && + s1.mutexes == s2.mutexes && + partialOrd.isLeq(s1.withGeneralizedVars(), s2.withGeneralizedVars()) + } private fun >, P : XcfaPrec> getXcfaArgBuilder( - analysis: Analysis, - lts: LTS>, XcfaAction>, - errorDetection: ErrorDetection) - : ArgBuilder = - ArgBuilder.create( - lts, - analysis, - getXcfaErrorPredicate(errorDetection) - ) + analysis: Analysis, + lts: LTS>, XcfaAction>, + errorDetection: ErrorDetection, +): ArgBuilder = + ArgBuilder.create(lts, analysis, getXcfaErrorPredicate(errorDetection)) fun >, P : XcfaPrec> getXcfaAbstractor( - analysis: Analysis, - waitlist: Waitlist<*>, - stopCriterion: StopCriterion<*, *>, - logger: Logger, - lts: LTS>, XcfaAction>, - errorDetection: ErrorDetection -): Abstractor>, XcfaAction, out XcfaPrec> = - XcfaAbstractor.builder(getXcfaArgBuilder(analysis, lts, errorDetection)) - .waitlist(waitlist as Waitlist>) // TODO: can we do this nicely? - .stopCriterion(stopCriterion as StopCriterion).logger(logger) - .projection { - if (it.xcfa!!.isInlined) it.processes - else it.processes.map { (_, p) -> p.locs.peek() } - } - .build() // TODO: can we do this nicely? + analysis: Analysis, + waitlist: Waitlist<*>, + stopCriterion: StopCriterion<*, *>, + logger: Logger, + lts: LTS>, XcfaAction>, + errorDetection: ErrorDetection, +): ArgAbstractor>, XcfaAction, out XcfaPrec> = + XcfaArgAbstractor.builder(getXcfaArgBuilder(analysis, lts, errorDetection)) + .waitlist(waitlist as Waitlist>) // TODO: can we do this nicely? + .stopCriterion(stopCriterion as StopCriterion) + .logger(logger) + .projection { + if (it.xcfa!!.isInlined) it.processes else it.processes.map { (_, p) -> p.locs.peek() } + } + .build() // TODO: can we do this nicely? /// EXPL -private fun getExplXcfaInitFunc(xcfa: XCFA, - solver: Solver): (XcfaPrec>) -> List>> { - val processInitState = xcfa.initProcedures.mapIndexed { i, it -> +private fun getExplXcfaInitFunc( + xcfa: XCFA, + solver: Solver, +): (XcfaPrec>) -> List>> { + val processInitState = + xcfa.initProcedures + .mapIndexed { i, it -> val initLocStack: LinkedList = LinkedList() initLocStack.add(it.first.initLoc) - Pair(i, XcfaProcessState(initLocStack, prefix = "T$i", - varLookup = LinkedList(listOf(createLookup(it.first, "T$i", ""))))) - }.toMap() - return { p -> - ExplInitFunc.create(solver, True()).getPtrInitFunc().getInitStates(p.p) - .map { XcfaState(xcfa, processInitState, it) } + Pair( + i, + XcfaProcessState( + initLocStack, + prefix = "T$i", + varLookup = LinkedList(listOf(createLookup(it.first, "T$i", ""))), + ), + ) + } + .toMap() + return { p -> + ExplInitFunc.create(solver, True()).getPtrInitFunc().getInitStates(p.p).map { + XcfaState(xcfa, processInitState, it) } + } } -private fun getExplXcfaTransFunc(solver: Solver, maxEnum: Int, isHavoc: Boolean): - (XcfaState>, XcfaAction, XcfaPrec>) -> List>> { - val explTransFunc = (ExplStmtTransFunc.create(solver, - maxEnum) as TransFunc).getPtrTransFunc(isHavoc) - return { s, a, p -> - val (newSt, newAct) = s.apply(a) - explTransFunc.getSuccStates(newSt.sGlobal, newAct, p.p.addVars( - listOf(s.processes.map { it.value.varLookup }.flatten(), - listOf(getTempLookup(a.label))).flatten())).map { newSt.withState(it) } - } +private fun getExplXcfaTransFunc( + solver: Solver, + maxEnum: Int, + isHavoc: Boolean, +): (XcfaState>, XcfaAction, XcfaPrec>) -> List< + XcfaState> + > { + val explTransFunc = + (ExplStmtTransFunc.create(solver, maxEnum) as TransFunc) + .getPtrTransFunc(isHavoc) + return { s, a, p -> + val (newSt, newAct) = s.apply(a) + explTransFunc + .getSuccStates( + newSt.sGlobal, + newAct, + p.p.addVars( + listOf(s.processes.map { it.value.varLookup }.flatten(), listOf(getTempLookup(a.label))) + .flatten() + ), + ) + .map { newSt.withState(it) } + } } -class ExplXcfaAnalysis(xcfa: XCFA, solver: Solver, maxEnum: Int, - partialOrd: PartialOrd>>, isHavoc: Boolean) : - XcfaAnalysis>( - corePartialOrd = partialOrd, - coreInitFunc = getExplXcfaInitFunc(xcfa, solver), - coreTransFunc = getExplXcfaTransFunc(solver, maxEnum, isHavoc) - ) +class ExplXcfaAnalysis( + xcfa: XCFA, + solver: Solver, + maxEnum: Int, + partialOrd: PartialOrd>>, + isHavoc: Boolean, +) : + XcfaAnalysis>( + corePartialOrd = partialOrd, + coreInitFunc = getExplXcfaInitFunc(xcfa, solver), + coreTransFunc = getExplXcfaTransFunc(solver, maxEnum, isHavoc), + ) /// PRED -private fun getPredXcfaInitFunc(xcfa: XCFA, - predAbstractor: PredAbstractor): (XcfaPrec>) -> List>> { - val processInitState = xcfa.initProcedures.mapIndexed { i, it -> +private fun getPredXcfaInitFunc( + xcfa: XCFA, + predAbstractor: PredAbstractor, +): (XcfaPrec>) -> List>> { + val processInitState = + xcfa.initProcedures + .mapIndexed { i, it -> val initLocStack: LinkedList = LinkedList() initLocStack.add(it.first.initLoc) - Pair(i, XcfaProcessState(initLocStack, prefix = "T$i", - varLookup = LinkedList(listOf(createLookup(it.first, "T$i", ""))))) - }.toMap() - return { p -> - PredInitFunc.create(predAbstractor, True()).getPtrInitFunc().getInitStates(p.p) - .map { XcfaState(xcfa, processInitState, it) } + Pair( + i, + XcfaProcessState( + initLocStack, + prefix = "T$i", + varLookup = LinkedList(listOf(createLookup(it.first, "T$i", ""))), + ), + ) + } + .toMap() + return { p -> + PredInitFunc.create(predAbstractor, True()).getPtrInitFunc().getInitStates(p.p).map { + XcfaState(xcfa, processInitState, it) } + } } -private fun getPredXcfaTransFunc(predAbstractor: PredAbstractors.PredAbstractor, isHavoc: Boolean): - (XcfaState>, XcfaAction, XcfaPrec>) -> List>> { - val predTransFunc = (PredTransFunc.create( - predAbstractor) as TransFunc).getPtrTransFunc(isHavoc) - return { s, a, p -> - val (newSt, newAct) = s.apply(a) - predTransFunc.getSuccStates(newSt.sGlobal, newAct, p.p.addVars( - s.processes.map { it.value.foldVarLookup() + getTempLookup(a.label) } - )).map { newSt.withState(it) } - } +private fun getPredXcfaTransFunc( + predAbstractor: PredAbstractors.PredAbstractor, + isHavoc: Boolean, +): (XcfaState>, XcfaAction, XcfaPrec>) -> List< + XcfaState> + > { + val predTransFunc = + (PredTransFunc.create(predAbstractor) as TransFunc) + .getPtrTransFunc(isHavoc) + return { s, a, p -> + val (newSt, newAct) = s.apply(a) + predTransFunc + .getSuccStates( + newSt.sGlobal, + newAct, + p.p.addVars(s.processes.map { it.value.foldVarLookup() + getTempLookup(a.label) }), + ) + .map { newSt.withState(it) } + } } -class PredXcfaAnalysis(xcfa: XCFA, solver: Solver, predAbstractor: PredAbstractor, - partialOrd: PartialOrd>>, isHavoc: Boolean) : - XcfaAnalysis>( - corePartialOrd = partialOrd, - coreInitFunc = getPredXcfaInitFunc(xcfa, predAbstractor), - coreTransFunc = getPredXcfaTransFunc(predAbstractor, isHavoc) - ) +class PredXcfaAnalysis( + xcfa: XCFA, + solver: Solver, + predAbstractor: PredAbstractor, + partialOrd: PartialOrd>>, + isHavoc: Boolean, +) : + XcfaAnalysis>( + corePartialOrd = partialOrd, + coreInitFunc = getPredXcfaInitFunc(xcfa, predAbstractor), + coreTransFunc = getPredXcfaTransFunc(predAbstractor, isHavoc), + ) diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaArgAbstractor.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaArgAbstractor.kt new file mode 100644 index 0000000000..bc2d2b816c --- /dev/null +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaArgAbstractor.kt @@ -0,0 +1,143 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.xcfa.analysis + +import com.google.common.base.Preconditions +import hu.bme.mit.theta.analysis.Action +import hu.bme.mit.theta.analysis.Prec +import hu.bme.mit.theta.analysis.State +import hu.bme.mit.theta.analysis.algorithm.arg.ARG +import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder +import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode +import hu.bme.mit.theta.analysis.algorithm.cegar.AbstractorResult +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor +import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterion +import hu.bme.mit.theta.analysis.reachedset.Partition +import hu.bme.mit.theta.analysis.waitlist.Waitlist +import hu.bme.mit.theta.common.logging.Logger +import java.util.function.Function + +class XcfaArgAbstractor( + argBuilder: ArgBuilder, + projection: Function?, + waitlist: Waitlist>, + stopCriterion: StopCriterion, + logger: Logger, +) : BasicArgAbstractor(argBuilder, projection, waitlist, stopCriterion, logger) { + + override fun check(arg: ARG, prec: P): AbstractorResult { + logger.write(Logger.Level.DETAIL, "| | Precision: %s%n", prec) + + if (!arg.isInitialized) { + logger.write(Logger.Level.SUBSTEP, "| | (Re)initializing ARG...") + argBuilder.init(arg, prec) + logger.write(Logger.Level.SUBSTEP, "done%n") + } + + assert(arg.isInitialized) + + logger.write( + Logger.Level.INFO, + "| | Starting ARG: %d nodes, %d incomplete, %d unsafe%n", + arg.nodes.count(), + arg.incompleteNodes.count(), + arg.unsafeNodes.count(), + ) + logger.write(Logger.Level.SUBSTEP, "| | Building ARG...") + + val reachedSet: Partition, *> = + Partition.of { n: ArgNode -> projection.apply(n.state) } + waitlist.clear() + + reachedSet.addAll(arg.nodes) + waitlist.addAll(arg.incompleteNodes) + + if (!stopCriterion.canStop(arg)) { + while (!waitlist.isEmpty) { + val node = waitlist.remove() + var newNodes: Collection>? = emptyList() + if ((node.state as XcfaState<*>).xcfa!!.isInlined) { + close(node, reachedSet[node]) + } else { + val expandProcedureCall = (node.state as XcfaState<*>) in (prec as XcfaPrec

).noPop + closePop(node, reachedSet[node], !expandProcedureCall) + } + if (!node.isSubsumed && !node.isTarget) { + newNodes = argBuilder.expand(node, prec) + reachedSet.addAll(newNodes) + waitlist.addAll(newNodes) + } + if (stopCriterion.canStop(arg, newNodes)) break + } + } + + logger.write(Logger.Level.SUBSTEP, "done%n") + logger.write( + Logger.Level.INFO, + "| | Finished ARG: %d nodes, %d incomplete, %d unsafe%n", + arg.nodes.count(), + arg.incompleteNodes.count(), + arg.unsafeNodes.count(), + ) + + waitlist.clear() // Optimization + + return if (arg.isSafe) { + Preconditions.checkState(arg.isComplete, "Returning incomplete ARG as safe") + AbstractorResult.safe() + } else { + AbstractorResult.unsafe() + } + } + + fun closePop(node: ArgNode, candidates: Collection>, popCovered: Boolean) { + if (!node.isLeaf) { + return + } + for (candidate in candidates) { + if (candidate.mayCover(node)) { + var onlyStackCovers = false + (node.state as XcfaState<*>).processes.forEach { (pid: Int, proc: XcfaProcessState) -> + if (proc != (candidate.state as XcfaState<*>).processes[pid]) { + if (popCovered) proc.popped = proc.locs.pop() + onlyStackCovers = true + } + } + if (!onlyStackCovers) { + node.cover(candidate) + } + return + } + } + } + + companion object { + + fun builder( + argBuilder: ArgBuilder + ): BasicArgAbstractor.Builder { + return Builder(argBuilder) + } + } + + class Builder(argBuilder: ArgBuilder) : + BasicArgAbstractor.Builder(argBuilder) { + + override fun build(): BasicArgAbstractor { + return XcfaArgAbstractor(argBuilder, projection, waitlist, stopCriterion, logger) + } + } +} diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt index ad0a385e5d..93410e0641 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt @@ -64,7 +64,7 @@ class XcfaSingleExprTraceRefiner, prec: P?): RefinerResult { + fun refineTemp(arg: ARG, prec: P?): RefinerResult> { Preconditions.checkNotNull(arg) Preconditions.checkNotNull(prec) assert(!arg.isSafe) { "ARG must be unsafe" } @@ -118,7 +118,7 @@ class XcfaSingleExprTraceRefiner, prec: P?): RefinerResult { + override fun refine(arg: ARG, prec: P?): RefinerResult> { Preconditions.checkNotNull(arg) Preconditions.checkNotNull

(prec) assert(!arg.isSafe) { "ARG must be unsafe" } diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt index b4aa758303..a04508f9cf 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.analysis -import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators import hu.bme.mit.theta.analysis.algorithm.SafetyResult -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner +import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions import hu.bme.mit.theta.analysis.expl.* import hu.bme.mit.theta.analysis.expr.refinement.* @@ -39,255 +38,309 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory import hu.bme.mit.theta.xcfa.analysis.coi.ConeOfInfluence import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread import hu.bme.mit.theta.xcfa.analysis.por.* +import java.util.* +import kotlin.random.Random import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource -import java.util.* -import kotlin.random.Random - class XcfaExplAnalysisTest { + companion object { - companion object { - - private val seed = 1001 - - @JvmStatic - fun data(): Collection> { - return listOf( - arrayOf("/00assignment.c", SafetyResult<*, *>::isUnsafe), - arrayOf("/01function.c", SafetyResult<*, *>::isUnsafe), - arrayOf("/02functionparam.c", SafetyResult<*, *>::isSafe), - arrayOf("/03nondetfunction.c", SafetyResult<*, *>::isUnsafe), - arrayOf("/04multithread.c", SafetyResult<*, *>::isUnsafe), - ) - } - } - - @ParameterizedTest - @MethodSource("data") - fun testNoporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - println("Testing NOPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val analysis = ExplXcfaAnalysis( - xcfa, - Z3LegacySolverFactory.getInstance().createSolver(), - 1, - getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd()), false - ) - - val lts = getXcfaLts() - - val abstractor = getXcfaAbstractor(analysis, - PriorityWaitlist.create( - ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs())), - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner>, ExplPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToExplPrec())) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - NullLogger.getInstance()) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testSporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - println("Testing SPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val analysis = ExplXcfaAnalysis( - xcfa, - Z3LegacySolverFactory.getInstance().createSolver(), - 1, - getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd()), false - ) - - val lts = XcfaSporLts(xcfa) - - val abstractor = getXcfaAbstractor(analysis, - PriorityWaitlist.create( - ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs())), - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner>, ExplPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToExplPrec())) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - NullLogger.getInstance()) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testDporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - XcfaDporLts.random = Random(seed) - println("Testing DPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val analysis = ExplXcfaAnalysis( - xcfa, - Z3LegacySolverFactory.getInstance().createSolver(), - 1, - XcfaDporLts.getPartialOrder(getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd())), false - ) - - val lts = XcfaDporLts(xcfa) - - val abstractor = getXcfaAbstractor(analysis, - lts.waitlist, - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner>, ExplPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToExplPrec())) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - ConsoleLogger( - Logger.Level.DETAIL)) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testAasporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - println("Testing AASPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val analysis = ExplXcfaAnalysis( - xcfa, - Z3LegacySolverFactory.getInstance().createSolver(), - 1, - getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd()), false - ) - - val lts = XcfaAasporLts(xcfa, mutableMapOf()) - - val abstractor = getXcfaAbstractor(analysis, - PriorityWaitlist.create( - ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs())), - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner, ExplPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToExplPrec())) - val atomicNodePruner = AtomicNodePruner>, XcfaAction>() - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, NullLogger.getInstance(), - atomicNodePruner) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, AasporRefiner.create(refiner, PruneStrategy.FULL, mutableMapOf())) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testAadporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - XcfaDporLts.random = Random(seed) - println("Testing AADPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val analysis = ExplXcfaAnalysis( - xcfa, - Z3LegacySolverFactory.getInstance().createSolver(), - 1, - XcfaDporLts.getPartialOrder(getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd())), false - ) - - val lts = XcfaAadporLts(xcfa) - - val abstractor = getXcfaAbstractor(analysis, - lts.waitlist, - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner(ItpRefToPtrPrec(ItpRefToExplPrec())) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - NullLogger.getInstance()) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) - - + private val seed = 1001 - Assertions.assertTrue(verdict(safetyResult)) + @JvmStatic + fun data(): Collection> { + return listOf( + arrayOf("/00assignment.c", SafetyResult<*, *>::isUnsafe), + arrayOf("/01function.c", SafetyResult<*, *>::isUnsafe), + arrayOf("/02functionparam.c", SafetyResult<*, *>::isSafe), + arrayOf("/03nondetfunction.c", SafetyResult<*, *>::isUnsafe), + arrayOf("/04multithread.c", SafetyResult<*, *>::isUnsafe), + ) } -} \ No newline at end of file + } + + @ParameterizedTest + @MethodSource("data") + fun testNoporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + println("Testing NOPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val analysis = + ExplXcfaAnalysis( + xcfa, + Z3LegacySolverFactory.getInstance().createSolver(), + 1, + getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd()), + false, + ) + + val lts = getXcfaLts() + + val abstractor = + getXcfaAbstractor( + analysis, + PriorityWaitlist.create( + ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + ), + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner>, ExplPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToExplPrec()) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testSporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + println("Testing SPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val analysis = + ExplXcfaAnalysis( + xcfa, + Z3LegacySolverFactory.getInstance().createSolver(), + 1, + getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd()), + false, + ) + + val lts = XcfaSporLts(xcfa) + + val abstractor = + getXcfaAbstractor( + analysis, + PriorityWaitlist.create( + ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + ), + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner>, ExplPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToExplPrec()) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testDporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + XcfaDporLts.random = Random(seed) + println("Testing DPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val analysis = + ExplXcfaAnalysis( + xcfa, + Z3LegacySolverFactory.getInstance().createSolver(), + 1, + XcfaDporLts.getPartialOrder(getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd())), + false, + ) + + val lts = XcfaDporLts(xcfa) + + val abstractor = + getXcfaAbstractor( + analysis, + lts.waitlist, + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner>, ExplPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToExplPrec()) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + ConsoleLogger(Logger.Level.DETAIL), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testAasporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + println("Testing AASPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val analysis = + ExplXcfaAnalysis( + xcfa, + Z3LegacySolverFactory.getInstance().createSolver(), + 1, + getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd()), + false, + ) + + val lts = XcfaAasporLts(xcfa, mutableMapOf()) + + val abstractor = + getXcfaAbstractor( + analysis, + PriorityWaitlist.create( + ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + ), + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner, ExplPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToExplPrec()) + ) + val atomicNodePruner = AtomicNodePruner>, XcfaAction>() + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + atomicNodePruner, + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = + ArgCegarChecker.create( + abstractor, + AasporRefiner.create(refiner, PruneStrategy.FULL, mutableMapOf()), + ) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testAadporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + XcfaDporLts.random = Random(seed) + println("Testing AADPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val analysis = + ExplXcfaAnalysis( + xcfa, + Z3LegacySolverFactory.getInstance().createSolver(), + 1, + XcfaDporLts.getPartialOrder(getPartialOrder(ExplOrd.getInstance().getPtrPartialOrd())), + false, + ) + + val lts = XcfaAadporLts(xcfa) + + val abstractor = + getXcfaAbstractor( + analysis, + lts.waitlist, + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner(ItpRefToPtrPrec(ItpRefToExplPrec())) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } +} diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt index e398b5ed07..a10e82f096 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.analysis -import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators import hu.bme.mit.theta.analysis.algorithm.SafetyResult -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner +import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions import hu.bme.mit.theta.analysis.expr.refinement.* import hu.bme.mit.theta.analysis.pred.* @@ -39,262 +38,316 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory import hu.bme.mit.theta.xcfa.analysis.coi.ConeOfInfluence import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread import hu.bme.mit.theta.xcfa.analysis.por.* +import java.util.* +import kotlin.random.Random import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource -import java.util.* -import kotlin.random.Random - class XcfaPredAnalysisTest { + companion object { - companion object { - - private val seed = 1001; - - @JvmStatic - fun data(): Collection> { - return listOf( - arrayOf("/00assignment.c", SafetyResult<*, *>::isUnsafe), - arrayOf("/01function.c", SafetyResult<*, *>::isUnsafe), - arrayOf("/02functionparam.c", SafetyResult<*, *>::isSafe), - arrayOf("/03nondetfunction.c", SafetyResult<*, *>::isUnsafe), - arrayOf("/04multithread.c", SafetyResult<*, *>::isUnsafe), - ) - } - } - - @ParameterizedTest - @MethodSource("data") - fun testNoporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - println("Testing NOPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val solver = Z3LegacySolverFactory.getInstance().createSolver() - val analysis = PredXcfaAnalysis( - xcfa, - solver, - PredAbstractors.cartesianAbstractor(solver), - getPartialOrder(PredOrd.create(solver).getPtrPartialOrd()), - false - ) - - val lts = getXcfaLts() - - val abstractor = getXcfaAbstractor(analysis, - PriorityWaitlist.create( - ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs())), - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner>, PredPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole()))) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - NullLogger.getInstance()) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testSporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - println("Testing SPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val solver = Z3LegacySolverFactory.getInstance().createSolver() - val analysis = PredXcfaAnalysis( - xcfa, - solver, - PredAbstractors.cartesianAbstractor(solver), - getPartialOrder(PredOrd.create(solver).getPtrPartialOrd()), false - ) - - val lts = XcfaSporLts(xcfa) - - val abstractor = getXcfaAbstractor(analysis, - PriorityWaitlist.create( - ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs())), - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner>, PredPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole()))) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - NullLogger.getInstance()) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testDporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - XcfaDporLts.random = Random(seed) - println("Testing DPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val solver = Z3LegacySolverFactory.getInstance().createSolver() - val analysis = PredXcfaAnalysis( - xcfa, - solver, - PredAbstractors.cartesianAbstractor(solver), - XcfaDporLts.getPartialOrder(getPartialOrder(PredOrd.create(solver).getPtrPartialOrd())), false - ) - - val lts = XcfaDporLts(xcfa) - - val abstractor = getXcfaAbstractor(analysis, - lts.waitlist, - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner>, PredPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole()))) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - ConsoleLogger( - Logger.Level.DETAIL)) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testAasporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - println("Testing AASPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val solver = Z3LegacySolverFactory.getInstance().createSolver() - val analysis = PredXcfaAnalysis( - xcfa, - solver, - PredAbstractors.cartesianAbstractor(solver), - getPartialOrder(PredOrd.create(solver).getPtrPartialOrd()), false - ) - - val lts = XcfaAasporLts(xcfa, mutableMapOf()) - - val abstractor = getXcfaAbstractor(analysis, - PriorityWaitlist.create( - ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs())), - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner, PredPrec, ItpRefutation>( - ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole()))) - val atomicNodePruner = AtomicNodePruner>, XcfaAction>() - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, NullLogger.getInstance(), - atomicNodePruner) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, AasporRefiner.create(refiner, PruneStrategy.FULL, mutableMapOf())) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) - - - - Assertions.assertTrue(verdict(safetyResult)) - } - - @ParameterizedTest - @MethodSource("data") - fun testAadporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { - XcfaDporLts.random = Random(seed) - println("Testing AADPOR on $filepath...") - val stream = javaClass.getResourceAsStream(filepath) - val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first - ConeOfInfluence = XcfaCoiMultiThread(xcfa) - - val solver = Z3LegacySolverFactory.getInstance().createSolver() - val analysis = PredXcfaAnalysis( - xcfa, - solver, - PredAbstractors.cartesianAbstractor(solver), - XcfaDporLts.getPartialOrder(getPartialOrder(PredOrd.create(solver).getPtrPartialOrd())), false - ) - - val lts = XcfaAadporLts(xcfa) - - val abstractor = getXcfaAbstractor(analysis, - lts.waitlist, - StopCriterions.firstCex>, XcfaAction>(), - ConsoleLogger(Logger.Level.DETAIL), - lts, - ErrorDetection.ERROR_LOCATION) as Abstractor>, XcfaAction, XcfaPrec>> - - val precRefiner = XcfaPrecRefiner( - ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole()))) - - val refiner = - XcfaSingleExprTraceRefiner.create( - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), - Z3LegacySolverFactory.getInstance().createItpSolver()), - precRefiner, PruneStrategy.FULL, - NullLogger.getInstance()) as Refiner>, XcfaAction, XcfaPrec>> - - val cegarChecker = - CegarChecker.create(abstractor, refiner) - - val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) - - + private val seed = 1001 - Assertions.assertTrue(verdict(safetyResult)) + @JvmStatic + fun data(): Collection> { + return listOf( + arrayOf("/00assignment.c", SafetyResult<*, *>::isUnsafe), + arrayOf("/01function.c", SafetyResult<*, *>::isUnsafe), + arrayOf("/02functionparam.c", SafetyResult<*, *>::isSafe), + arrayOf("/03nondetfunction.c", SafetyResult<*, *>::isUnsafe), + arrayOf("/04multithread.c", SafetyResult<*, *>::isUnsafe), + ) } -} \ No newline at end of file + } + + @ParameterizedTest + @MethodSource("data") + fun testNoporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + println("Testing NOPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val solver = Z3LegacySolverFactory.getInstance().createSolver() + val analysis = + PredXcfaAnalysis( + xcfa, + solver, + PredAbstractors.cartesianAbstractor(solver), + getPartialOrder(PredOrd.create(solver).getPtrPartialOrd()), + false, + ) + + val lts = getXcfaLts() + + val abstractor = + getXcfaAbstractor( + analysis, + PriorityWaitlist.create( + ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + ), + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner>, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole())) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testSporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + println("Testing SPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val solver = Z3LegacySolverFactory.getInstance().createSolver() + val analysis = + PredXcfaAnalysis( + xcfa, + solver, + PredAbstractors.cartesianAbstractor(solver), + getPartialOrder(PredOrd.create(solver).getPtrPartialOrd()), + false, + ) + + val lts = XcfaSporLts(xcfa) + + val abstractor = + getXcfaAbstractor( + analysis, + PriorityWaitlist.create( + ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + ), + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner>, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole())) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testDporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + XcfaDporLts.random = Random(seed) + println("Testing DPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val solver = Z3LegacySolverFactory.getInstance().createSolver() + val analysis = + PredXcfaAnalysis( + xcfa, + solver, + PredAbstractors.cartesianAbstractor(solver), + XcfaDporLts.getPartialOrder(getPartialOrder(PredOrd.create(solver).getPtrPartialOrd())), + false, + ) + + val lts = XcfaDporLts(xcfa) + + val abstractor = + getXcfaAbstractor( + analysis, + lts.waitlist, + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner>, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole())) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + ConsoleLogger(Logger.Level.DETAIL), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testAasporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + println("Testing AASPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val solver = Z3LegacySolverFactory.getInstance().createSolver() + val analysis = + PredXcfaAnalysis( + xcfa, + solver, + PredAbstractors.cartesianAbstractor(solver), + getPartialOrder(PredOrd.create(solver).getPtrPartialOrd()), + false, + ) + + val lts = XcfaAasporLts(xcfa, mutableMapOf()) + + val abstractor = + getXcfaAbstractor( + analysis, + PriorityWaitlist.create( + ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + ), + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole())) + ) + val atomicNodePruner = AtomicNodePruner>, XcfaAction>() + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + atomicNodePruner, + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = + ArgCegarChecker.create( + abstractor, + AasporRefiner.create(refiner, PruneStrategy.FULL, mutableMapOf()), + ) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } + + @ParameterizedTest + @MethodSource("data") + fun testAadporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { + XcfaDporLts.random = Random(seed) + println("Testing AADPOR on $filepath...") + val stream = javaClass.getResourceAsStream(filepath) + val xcfa = getXcfaFromC(stream!!, ParseContext(), false, false, NullLogger.getInstance()).first + ConeOfInfluence = XcfaCoiMultiThread(xcfa) + + val solver = Z3LegacySolverFactory.getInstance().createSolver() + val analysis = + PredXcfaAnalysis( + xcfa, + solver, + PredAbstractors.cartesianAbstractor(solver), + XcfaDporLts.getPartialOrder(getPartialOrder(PredOrd.create(solver).getPtrPartialOrd())), + false, + ) + + val lts = XcfaAadporLts(xcfa) + + val abstractor = + getXcfaAbstractor( + analysis, + lts.waitlist, + StopCriterions.firstCex>, XcfaAction>(), + ConsoleLogger(Logger.Level.DETAIL), + lts, + ErrorDetection.ERROR_LOCATION, + ) + as ArgAbstractor>, XcfaAction, XcfaPrec>> + + val precRefiner = + XcfaPrecRefiner( + ItpRefToPtrPrec(ItpRefToPredPrec(ExprSplitters.whole())) + ) + + val refiner = + XcfaSingleExprTraceRefiner.create( + ExprTraceBwBinItpChecker.create( + BoolExprs.True(), + BoolExprs.True(), + Z3LegacySolverFactory.getInstance().createItpSolver(), + ), + precRefiner, + PruneStrategy.FULL, + NullLogger.getInstance(), + ) as ArgRefiner>, XcfaAction, XcfaPrec>> + + val cegarChecker = ArgCegarChecker.create(abstractor, refiner) + + val safetyResult = cegarChecker.check(XcfaPrec(PtrPrec(PredPrec.of(), emptySet()))) + + Assertions.assertTrue(verdict(safetyResult)) + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt index 8c39486021..f8bf86f8d2 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt @@ -23,9 +23,9 @@ import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.arg.ARG -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner import hu.bme.mit.theta.analysis.expr.ExprAction import hu.bme.mit.theta.analysis.expr.ExprState import hu.bme.mit.theta.analysis.expr.refinement.* @@ -43,14 +43,20 @@ import hu.bme.mit.theta.xcfa.cli.params.* import hu.bme.mit.theta.xcfa.cli.utils.getSolver import hu.bme.mit.theta.xcfa.model.XCFA -fun getCegarChecker(xcfa: XCFA, mcm: MCM, +fun getCegarChecker( + xcfa: XCFA, mcm: MCM, config: XcfaConfig<*, *>, - logger: Logger): SafetyChecker, XcfaAction>, Trace>, XcfaAction>, XcfaPrec<*>> { + logger: Logger +): SafetyChecker, XcfaAction>, Trace>, XcfaAction>, XcfaPrec<*>> { val cegarConfig = config.backendConfig.specConfig as CegarConfig - val abstractionSolverFactory: SolverFactory = getSolver(cegarConfig.abstractorConfig.abstractionSolver, - cegarConfig.abstractorConfig.validateAbstractionSolver) - val refinementSolverFactory: SolverFactory = getSolver(cegarConfig.refinerConfig.refinementSolver, - cegarConfig.refinerConfig.validateRefinementSolver) + val abstractionSolverFactory: SolverFactory = getSolver( + cegarConfig.abstractorConfig.abstractionSolver, + cegarConfig.abstractorConfig.validateAbstractionSolver + ) + val refinementSolverFactory: SolverFactory = getSolver( + cegarConfig.refinerConfig.refinementSolver, + cegarConfig.refinerConfig.validateRefinementSolver + ) val ignoredVarRegistry = mutableMapOf, MutableSet>() @@ -59,16 +65,18 @@ fun getCegarChecker(xcfa: XCFA, mcm: MCM, (cegarConfig.coi.porLts as XcfaDporLts).waitlist } else { PriorityWaitlist.create>, XcfaAction>>( - cegarConfig.abstractorConfig.search.getComp(xcfa)) + cegarConfig.abstractorConfig.search.getComp(xcfa) + ) } val abstractionSolverInstance = abstractionSolverFactory.createSolver() val globalStatePartialOrd: PartialOrd> = cegarConfig.abstractorConfig.domain.partialOrd( - abstractionSolverInstance) as PartialOrd> + abstractionSolverInstance + ) as PartialOrd> val corePartialOrd: PartialOrd>> = if (xcfa.isInlined) getPartialOrder(globalStatePartialOrd) else getStackPartialOrder(globalStatePartialOrd) - val abstractor: Abstractor = cegarConfig.abstractorConfig.domain.abstractor( + val abstractor: ArgAbstractor = cegarConfig.abstractorConfig.domain.abstractor( xcfa, abstractionSolverInstance, cegarConfig.abstractorConfig.maxEnum, @@ -83,7 +91,7 @@ fun getCegarChecker(xcfa: XCFA, mcm: MCM, corePartialOrd }, cegarConfig.abstractorConfig.havocMemory - ) as Abstractor + ) as ArgAbstractor val ref: ExprTraceChecker = cegarConfig.refinerConfig.refinement.refiner(refinementSolverFactory, cegarConfig.cexMonitor) @@ -91,43 +99,50 @@ fun getCegarChecker(xcfa: XCFA, mcm: MCM, val precRefiner: PrecRefiner = cegarConfig.abstractorConfig.domain.itpPrecRefiner(cegarConfig.refinerConfig.exprSplitter.exprSplitter) as PrecRefiner - val atomicNodePruner: NodePruner = cegarConfig.abstractorConfig.domain.nodePruner as NodePruner - val refiner: Refiner = + val atomicNodePruner: NodePruner = + cegarConfig.abstractorConfig.domain.nodePruner as NodePruner + val refiner: ArgRefiner = if (cegarConfig.refinerConfig.refinement == Refinement.MULTI_SEQ) if (cegarConfig.porLevel == POR.AASPOR) - MultiExprTraceRefiner.create(ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger, - atomicNodePruner) + MultiExprTraceRefiner.create( + ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger, + atomicNodePruner + ) else MultiExprTraceRefiner.create(ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger) else if (cegarConfig.porLevel == POR.AASPOR) - XcfaSingleExprTraceRefiner.create(ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger, - atomicNodePruner) + XcfaSingleExprTraceRefiner.create( + ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger, + atomicNodePruner + ) else XcfaSingleExprTraceRefiner.create(ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger) val cegarChecker = if (cegarConfig.porLevel == POR.AASPOR) - CegarChecker.create( + ArgCegarChecker.create( abstractor, AasporRefiner.create(refiner, cegarConfig.refinerConfig.pruneStrategy, ignoredVarRegistry), logger ) else - CegarChecker.create(abstractor, refiner, logger) + ArgCegarChecker.create(abstractor, refiner, logger) // initialize monitors MonitorCheckpoint.reset() if (cegarConfig.cexMonitor == CexMonitorOptions.CHECK) { - val cm = CexMonitor(logger, cegarChecker.arg) + val cm = CexMonitor(logger, cegarChecker.witness) MonitorCheckpoint.register(cm, "CegarChecker.unsafeARG") } return object : SafetyChecker, XcfaAction>, Trace>, XcfaAction>, XcfaPrec<*>> { override fun check( - prec: XcfaPrec<*>?): SafetyResult, XcfaAction>, Trace>, XcfaAction>> { + prec: XcfaPrec<*>? + ): SafetyResult, XcfaAction>, Trace>, XcfaAction>> { return cegarChecker.check( - prec) as SafetyResult, XcfaAction>, Trace>, XcfaAction>> + prec + ) as SafetyResult, XcfaAction>, Trace>, XcfaAction>> } override fun check(): SafetyResult, XcfaAction>, Trace>, XcfaAction>> { diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/params/ParamValues.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/params/ParamValues.kt index ac5b3d3236..8f1695855c 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/params/ParamValues.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/params/ParamValues.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.params import com.google.gson.reflect.TypeToken @@ -23,7 +22,7 @@ import hu.bme.mit.theta.analysis.Prec import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators.ArgNodeComparator -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterion import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions import hu.bme.mit.theta.analysis.expl.ExplPrec @@ -55,309 +54,386 @@ import hu.bme.mit.theta.xcfa.model.XCFA import java.lang.reflect.Type enum class InputType { - C, - LLVM, - JSON, - DSL, - CHC, - LITMUS, + C, + LLVM, + JSON, + DSL, + CHC, + LITMUS, } enum class Backend { - CEGAR, - BOUNDED, - CHC, - OC, - LAZY, - PORTFOLIO, - NONE, + CEGAR, + BOUNDED, + CHC, + OC, + LAZY, + PORTFOLIO, + NONE, } enum class POR( - val getLts: (XCFA, MutableMap, MutableSet>) -> LTS>, XcfaAction>, - val isDynamic: Boolean, - val isAbstractionAware: Boolean + val getLts: + (XCFA, MutableMap, MutableSet>) -> LTS< + XcfaState>, + XcfaAction, + >, + val isDynamic: Boolean, + val isAbstractionAware: Boolean, ) { - NOPOR({ _, _ -> getXcfaLts() }, false, false), - SPOR({ xcfa, _ -> XcfaSporLts(xcfa) }, false, false), - AASPOR({ xcfa, registry -> XcfaAasporLts(xcfa, registry) }, false, true), - DPOR({ xcfa, _ -> XcfaDporLts(xcfa) }, true, false), - AADPOR({ xcfa, _ -> XcfaAadporLts(xcfa) }, true, true) + NOPOR({ _, _ -> getXcfaLts() }, false, false), + SPOR({ xcfa, _ -> XcfaSporLts(xcfa) }, false, false), + AASPOR({ xcfa, registry -> XcfaAasporLts(xcfa, registry) }, false, true), + DPOR({ xcfa, _ -> XcfaDporLts(xcfa) }, true, false), + AADPOR({ xcfa, _ -> XcfaAadporLts(xcfa) }, true, true), } enum class Strategy { - DIRECT, - SERVER, - SERVER_DEBUG, - PORTFOLIO + DIRECT, + SERVER, + SERVER_DEBUG, + PORTFOLIO, } // TODO partial orders nicely enum class Domain( - val abstractor: ( - xcfa: XCFA, - solver: Solver, - maxEnum: Int, - waitlist: Waitlist>, XcfaAction>>, - stopCriterion: StopCriterion>, XcfaAction>, - logger: Logger, - lts: LTS>, XcfaAction>, - errorDetectionType: ErrorDetection, - partialOrd: PartialOrd>>, - isHavoc: Boolean - ) -> Abstractor, - val itpPrecRefiner: (exprSplitter: ExprSplitter) -> PrecRefiner, - val initPrec: (XCFA, InitPrec) -> XcfaPrec>, - val partialOrd: (Solver) -> PartialOrd>, - val nodePruner: NodePruner, - val stateType: Type + val abstractor: + ( + xcfa: XCFA, + solver: Solver, + maxEnum: Int, + waitlist: Waitlist>, XcfaAction>>, + stopCriterion: StopCriterion>, XcfaAction>, + logger: Logger, + lts: LTS>, XcfaAction>, + errorDetectionType: ErrorDetection, + partialOrd: PartialOrd>>, + isHavoc: Boolean, + ) -> ArgAbstractor, + val itpPrecRefiner: + (exprSplitter: ExprSplitter) -> PrecRefiner< + out ExprState, + out ExprAction, + out Prec, + out Refutation, + >, + val initPrec: (XCFA, InitPrec) -> XcfaPrec>, + val partialOrd: (Solver) -> PartialOrd>, + val nodePruner: NodePruner, + val stateType: Type, ) { - EXPL( - abstractor = { a, b, c, d, e, f, g, h, i, j -> - getXcfaAbstractor(ExplXcfaAnalysis(a, b, c, i as PartialOrd>>, j), d, - e, f, g, h) - }, - itpPrecRefiner = { - XcfaPrecRefiner, ExplPrec, ItpRefutation>(ItpRefToPtrPrec(ItpRefToExplPrec())) - }, - initPrec = { x, ip -> ip.explPrec(x) }, - partialOrd = { PartialOrd { s1, s2 -> s1.isLeq(s2) }.getPtrPartialOrd() }, - nodePruner = AtomicNodePruner>, XcfaAction>(), - stateType = TypeToken.get(ExplState::class.java).type - ), - PRED_BOOL( - abstractor = { a, b, c, d, e, f, g, h, i, j -> - getXcfaAbstractor(PredXcfaAnalysis(a, b, PredAbstractors.booleanAbstractor(b), - i as PartialOrd>>, j), d, e, f, g, h) - }, - itpPrecRefiner = { a -> - XcfaPrecRefiner, PredPrec, ItpRefutation>(ItpRefToPtrPrec(ItpRefToPredPrec(a))) - }, - initPrec = { x, ip -> ip.predPrec(x) }, - partialOrd = { solver -> PredOrd.create(solver).getPtrPartialOrd() }, - nodePruner = AtomicNodePruner>, XcfaAction>(), - stateType = TypeToken.get(PredState::class.java).type - ), - PRED_CART( - abstractor = { a, b, c, d, e, f, g, h, i, j -> - getXcfaAbstractor(PredXcfaAnalysis(a, b, PredAbstractors.cartesianAbstractor(b), - i as PartialOrd>>, j), d, e, f, g, h) - }, - itpPrecRefiner = { a -> - XcfaPrecRefiner, PredPrec, ItpRefutation>(ItpRefToPtrPrec(ItpRefToPredPrec(a))) - }, - initPrec = { x, ip -> ip.predPrec(x) }, - partialOrd = { solver -> PredOrd.create(solver).getPtrPartialOrd() }, - nodePruner = AtomicNodePruner>, XcfaAction>(), - stateType = TypeToken.get(PredState::class.java).type - ), - PRED_SPLIT( - abstractor = { a, b, c, d, e, f, g, h, i, j -> - getXcfaAbstractor(PredXcfaAnalysis(a, b, PredAbstractors.booleanSplitAbstractor(b), - i as PartialOrd>>, j), d, e, f, g, h) - }, - itpPrecRefiner = { a -> - XcfaPrecRefiner, PredPrec, ItpRefutation>(ItpRefToPtrPrec(ItpRefToPredPrec(a))) - }, - initPrec = { x, ip -> ip.predPrec(x) }, - partialOrd = { solver -> PredOrd.create(solver).getPtrPartialOrd() }, - nodePruner = AtomicNodePruner>, XcfaAction>(), - stateType = TypeToken.get(PredState::class.java).type - ), + EXPL( + abstractor = { a, b, c, d, e, f, g, h, i, j -> + getXcfaAbstractor( + ExplXcfaAnalysis(a, b, c, i as PartialOrd>>, j), + d, + e, + f, + g, + h, + ) + }, + itpPrecRefiner = { + XcfaPrecRefiner, ExplPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToExplPrec()) + ) + }, + initPrec = { x, ip -> ip.explPrec(x) }, + partialOrd = { PartialOrd { s1, s2 -> s1.isLeq(s2) }.getPtrPartialOrd() }, + nodePruner = AtomicNodePruner>, XcfaAction>(), + stateType = TypeToken.get(ExplState::class.java).type, + ), + PRED_BOOL( + abstractor = { a, b, c, d, e, f, g, h, i, j -> + getXcfaAbstractor( + PredXcfaAnalysis( + a, + b, + PredAbstractors.booleanAbstractor(b), + i as PartialOrd>>, + j, + ), + d, + e, + f, + g, + h, + ) + }, + itpPrecRefiner = { a -> + XcfaPrecRefiner, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(a)) + ) + }, + initPrec = { x, ip -> ip.predPrec(x) }, + partialOrd = { solver -> PredOrd.create(solver).getPtrPartialOrd() }, + nodePruner = AtomicNodePruner>, XcfaAction>(), + stateType = TypeToken.get(PredState::class.java).type, + ), + PRED_CART( + abstractor = { a, b, c, d, e, f, g, h, i, j -> + getXcfaAbstractor( + PredXcfaAnalysis( + a, + b, + PredAbstractors.cartesianAbstractor(b), + i as PartialOrd>>, + j, + ), + d, + e, + f, + g, + h, + ) + }, + itpPrecRefiner = { a -> + XcfaPrecRefiner, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(a)) + ) + }, + initPrec = { x, ip -> ip.predPrec(x) }, + partialOrd = { solver -> PredOrd.create(solver).getPtrPartialOrd() }, + nodePruner = AtomicNodePruner>, XcfaAction>(), + stateType = TypeToken.get(PredState::class.java).type, + ), + PRED_SPLIT( + abstractor = { a, b, c, d, e, f, g, h, i, j -> + getXcfaAbstractor( + PredXcfaAnalysis( + a, + b, + PredAbstractors.booleanSplitAbstractor(b), + i as PartialOrd>>, + j, + ), + d, + e, + f, + g, + h, + ) + }, + itpPrecRefiner = { a -> + XcfaPrecRefiner, PredPrec, ItpRefutation>( + ItpRefToPtrPrec(ItpRefToPredPrec(a)) + ) + }, + initPrec = { x, ip -> ip.predPrec(x) }, + partialOrd = { solver -> PredOrd.create(solver).getPtrPartialOrd() }, + nodePruner = AtomicNodePruner>, XcfaAction>(), + stateType = TypeToken.get(PredState::class.java).type, + ), } enum class Refinement( - val refiner: (solverFactory: SolverFactory, monitorOption: CexMonitorOptions) -> ExprTraceChecker, - val stopCriterion: StopCriterion>, XcfaAction>, + val refiner: + (solverFactory: SolverFactory, monitorOption: CexMonitorOptions) -> ExprTraceChecker< + out Refutation + >, + val stopCriterion: StopCriterion>, XcfaAction>, ) { - FW_BIN_ITP( - refiner = { s, _ -> - ExprTraceFwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) - }, - stopCriterion = StopCriterions.firstCex(), - ), - BW_BIN_ITP( - refiner = { s, _ -> - ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) - }, - stopCriterion = StopCriterions.firstCex() - ), - SEQ_ITP( - refiner = { s, _ -> - ExprTraceSeqItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) - }, - stopCriterion = StopCriterions.firstCex() - ), - MULTI_SEQ( - refiner = { s, m -> - if (m == CexMonitorOptions.CHECK) error("CexMonitor is not implemented for MULTI_SEQ") - ExprTraceSeqItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) - }, - stopCriterion = StopCriterions.fullExploration() - ), - UNSAT_CORE( - refiner = { s, _ -> - ExprTraceUnsatCoreChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - }, - stopCriterion = StopCriterions.firstCex() - ), - UCB( - refiner = { s, _ -> - ExprTraceUCBChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - }, - stopCriterion = StopCriterions.firstCex() - ), - - NWT_SP( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withoutIT().withSP().withoutLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_WP( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withoutIT().withWP().withoutLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_SP_LV( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withoutIT().withSP().withLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_WP_LV( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withoutIT().withWP().withLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_IT_WP( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withIT().withWP().withoutLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_IT_SP( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withIT().withSP().withoutLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_IT_WP_LV( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withIT().withWP().withLV() - }, - stopCriterion = StopCriterions.firstCex() - ), - NWT_IT_SP_LV( - refiner = { s, _ -> - ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) - .withIT().withSP().withLV() - }, - stopCriterion = StopCriterions.firstCex() - ) + FW_BIN_ITP( + refiner = { s, _ -> + ExprTraceFwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) + }, + stopCriterion = StopCriterions.firstCex(), + ), + BW_BIN_ITP( + refiner = { s, _ -> + ExprTraceBwBinItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) + }, + stopCriterion = StopCriterions.firstCex(), + ), + SEQ_ITP( + refiner = { s, _ -> + ExprTraceSeqItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) + }, + stopCriterion = StopCriterions.firstCex(), + ), + MULTI_SEQ( + refiner = { s, m -> + if (m == CexMonitorOptions.CHECK) error("CexMonitor is not implemented for MULTI_SEQ") + ExprTraceSeqItpChecker.create(BoolExprs.True(), BoolExprs.True(), s.createItpSolver()) + }, + stopCriterion = StopCriterions.fullExploration(), + ), + UNSAT_CORE( + refiner = { s, _ -> + ExprTraceUnsatCoreChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + }, + stopCriterion = StopCriterions.firstCex(), + ), + UCB( + refiner = { s, _ -> + ExprTraceUCBChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_SP( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withoutIT() + .withSP() + .withoutLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_WP( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withoutIT() + .withWP() + .withoutLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_SP_LV( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withoutIT() + .withSP() + .withLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_WP_LV( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withoutIT() + .withWP() + .withLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_IT_WP( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withIT() + .withWP() + .withoutLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_IT_SP( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withIT() + .withSP() + .withoutLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_IT_WP_LV( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withIT() + .withWP() + .withLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), + NWT_IT_SP_LV( + refiner = { s, _ -> + ExprTraceNewtonChecker.create(BoolExprs.True(), BoolExprs.True(), s.createUCSolver()) + .withIT() + .withSP() + .withLV() + }, + stopCriterion = StopCriterions.firstCex(), + ), } - enum class ExprSplitterOptions(val exprSplitter: ExprSplitter) { - WHOLE(ExprSplitters.whole()), - CONJUNCTS(ExprSplitters.conjuncts()), - ATOMS(ExprSplitters.atoms()); + WHOLE(ExprSplitters.whole()), + CONJUNCTS(ExprSplitters.conjuncts()), + ATOMS(ExprSplitters.atoms()), } enum class Search { - BFS { + BFS { - override fun getComp(cfa: XCFA): ArgNodeComparator { - return ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), - ArgNodeComparators.bfs()) - } - }, - DFS { + override fun getComp(cfa: XCFA): ArgNodeComparator { + return ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.bfs()) + } + }, + DFS { - override fun getComp(cfa: XCFA): ArgNodeComparator { - return ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), - ArgNodeComparators.dfs()) - } - }, - ERR { + override fun getComp(cfa: XCFA): ArgNodeComparator { + return ArgNodeComparators.combine(ArgNodeComparators.targetFirst(), ArgNodeComparators.dfs()) + } + }, + ERR { - override fun getComp(cfa: XCFA): ArgNodeComparator { - return XcfaDistToErrComparator(cfa) - } - }; + override fun getComp(cfa: XCFA): ArgNodeComparator { + return XcfaDistToErrComparator(cfa) + } + }; - abstract fun getComp(cfa: XCFA): ArgNodeComparator + abstract fun getComp(cfa: XCFA): ArgNodeComparator } enum class InitPrec( - val explPrec: (xcfa: XCFA) -> XcfaPrec>, - val predPrec: (xcfa: XCFA) -> XcfaPrec>, + val explPrec: (xcfa: XCFA) -> XcfaPrec>, + val predPrec: (xcfa: XCFA) -> XcfaPrec>, ) { - EMPTY( - explPrec = { XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet())) }, - predPrec = { XcfaPrec(PtrPrec(PredPrec.of(), emptySet())) } - ), - ALLVARS( - explPrec = { xcfa -> XcfaPrec(PtrPrec(ExplPrec.of(xcfa.collectVars()), emptySet())) }, - predPrec = { error("ALLVARS is not interpreted for the predicate domain.") } - ), - ALLGLOBALS( - explPrec = { xcfa -> XcfaPrec(PtrPrec(ExplPrec.of(xcfa.vars.map { it.wrappedVar }), emptySet())) }, - predPrec = { error("ALLGLOBALS is not interpreted for the predicate domain.") } - ), - ALLASSUMES( - explPrec = { xcfa -> - XcfaPrec( - PtrPrec(ExplPrec.of(xcfa.collectAssumes().flatMap(ExprUtils::getVars)), emptySet())) - }, - predPrec = { xcfa -> XcfaPrec(PtrPrec(PredPrec.of(xcfa.collectAssumes()), emptySet())) }, - ), - + EMPTY( + explPrec = { XcfaPrec(PtrPrec(ExplPrec.empty(), emptySet())) }, + predPrec = { XcfaPrec(PtrPrec(PredPrec.of(), emptySet())) }, + ), + ALLVARS( + explPrec = { xcfa -> XcfaPrec(PtrPrec(ExplPrec.of(xcfa.collectVars()), emptySet())) }, + predPrec = { error("ALLVARS is not interpreted for the predicate domain.") }, + ), + ALLGLOBALS( + explPrec = { xcfa -> + XcfaPrec(PtrPrec(ExplPrec.of(xcfa.vars.map { it.wrappedVar }), emptySet())) + }, + predPrec = { error("ALLGLOBALS is not interpreted for the predicate domain.") }, + ), + ALLASSUMES( + explPrec = { xcfa -> + XcfaPrec(PtrPrec(ExplPrec.of(xcfa.collectAssumes().flatMap(ExprUtils::getVars)), emptySet())) + }, + predPrec = { xcfa -> XcfaPrec(PtrPrec(PredPrec.of(xcfa.collectAssumes()), emptySet())) }, + ), } enum class ConeOfInfluenceMode( - val getLts: (XCFA, MutableMap, MutableSet>, POR) -> LTS>, XcfaAction> + val getLts: + (XCFA, MutableMap, MutableSet>, POR) -> LTS< + XcfaState>, + XcfaAction, + > ) { - NO_COI({ xcfa, ivr, por -> - por.getLts(xcfa, ivr).also { NO_COI.porLts = it } - }), - COI({ xcfa, ivr, por -> - ConeOfInfluence.coreLts = por.getLts(xcfa, ivr).also { COI.porLts = it } - ConeOfInfluence.lts - }), - POR_COI({ xcfa, ivr, por -> - ConeOfInfluence.coreLts = getXcfaLts() - if (por.isAbstractionAware) XcfaAasporCoiLts(xcfa, ivr, ConeOfInfluence.lts) - else XcfaSporCoiLts(xcfa, ConeOfInfluence.lts) - }), - POR_COI_POR({ xcfa, ivr, por -> - ConeOfInfluence.coreLts = por.getLts(xcfa, ivr).also { POR_COI_POR.porLts = it } - if (por.isAbstractionAware) XcfaAasporCoiLts(xcfa, ivr, ConeOfInfluence.lts) - else XcfaSporCoiLts(xcfa, ConeOfInfluence.lts) - }) - ; + NO_COI({ xcfa, ivr, por -> por.getLts(xcfa, ivr).also { NO_COI.porLts = it } }), + COI({ xcfa, ivr, por -> + ConeOfInfluence.coreLts = por.getLts(xcfa, ivr).also { COI.porLts = it } + ConeOfInfluence.lts + }), + POR_COI({ xcfa, ivr, por -> + ConeOfInfluence.coreLts = getXcfaLts() + if (por.isAbstractionAware) XcfaAasporCoiLts(xcfa, ivr, ConeOfInfluence.lts) + else XcfaSporCoiLts(xcfa, ConeOfInfluence.lts) + }), + POR_COI_POR({ xcfa, ivr, por -> + ConeOfInfluence.coreLts = por.getLts(xcfa, ivr).also { POR_COI_POR.porLts = it } + if (por.isAbstractionAware) XcfaAasporCoiLts(xcfa, ivr, ConeOfInfluence.lts) + else XcfaSporCoiLts(xcfa, ConeOfInfluence.lts) + }); - var porLts: LTS>, XcfaAction>? = null + var porLts: LTS>, XcfaAction>? = null } // TODO CexMonitor: disable for multi_seq // TODO add new monitor to xsts cli enum class CexMonitorOptions { - CHECK, - DISABLE + CHECK, + DISABLE, } diff --git a/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java b/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java index 35b38b2a27..016d828fcb 100644 --- a/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java +++ b/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/config/XstsConfigBuilder.java @@ -13,18 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xsts.analysis.config; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; + import hu.bme.mit.theta.analysis.*; +import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators; -import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarChecker; -import hu.bme.mit.theta.analysis.algorithm.cegar.Refiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterion; import hu.bme.mit.theta.analysis.algorithm.cegar.abstractor.StopCriterions; import hu.bme.mit.theta.analysis.expl.*; @@ -60,16 +62,12 @@ import hu.bme.mit.theta.xsts.analysis.initprec.*; import hu.bme.mit.theta.xsts.analysis.util.XstsCombineExtractUtilsKt; import hu.bme.mit.theta.xsts.analysis.util.XstsControlInitFuncKt; - import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; - public class XstsConfigBuilder { //////////// CEGAR configuration //////////// @@ -94,20 +92,26 @@ public enum Domain { public enum Refinement { FW_BIN_ITP { @Override - public ExprTraceChecker getItpExprTraceChecker(Expr init, Expr target, ItpSolver solver) { + public ExprTraceChecker getItpExprTraceChecker( + Expr init, Expr target, ItpSolver solver) { return ExprTraceFwBinItpChecker.create(init, target, solver); } - }, BW_BIN_ITP { + }, + BW_BIN_ITP { @Override - public ExprTraceChecker getItpExprTraceChecker(Expr init, Expr target, ItpSolver solver) { + public ExprTraceChecker getItpExprTraceChecker( + Expr init, Expr target, ItpSolver solver) { return ExprTraceBwBinItpChecker.create(init, target, solver); } - }, SEQ_ITP { + }, + SEQ_ITP { @Override - public ExprTraceChecker getItpExprTraceChecker(Expr init, Expr target, ItpSolver solver) { + public ExprTraceChecker getItpExprTraceChecker( + Expr init, Expr target, ItpSolver solver) { return ExprTraceSeqItpChecker.create(init, target, solver); } - }, UNSAT_CORE, + }, + UNSAT_CORE, MULTI_SEQ { @Override public StopCriterion getStopCriterion() { @@ -115,19 +119,20 @@ public StopCriterion getStopCriterion() { } @Override - public ExprTraceChecker getItpExprTraceChecker(Expr init, Expr target, ItpSolver solver) { + public ExprTraceChecker getItpExprTraceChecker( + Expr init, Expr target, ItpSolver solver) { return ExprTraceSeqItpChecker.create(init, target, solver); } @Override - public Refiner, XstsAction, P> - createRefiner( - ExprTraceChecker traceChecker, - RefutationToPrec refToPrec, - PruneStrategy pruneStrategy, - Logger logger - ) { - return MultiExprTraceRefiner.create(traceChecker, JoiningPrecRefiner.create(refToPrec), pruneStrategy, logger); + public + ArgRefiner, XstsAction, P> createRefiner( + ExprTraceChecker traceChecker, + RefutationToPrec refToPrec, + PruneStrategy pruneStrategy, + Logger logger) { + return MultiExprTraceRefiner.create( + traceChecker, JoiningPrecRefiner.create(refToPrec), pruneStrategy, logger); } }; @@ -136,23 +141,22 @@ public StopCriterion getStopCriterion() { } public ExprTraceChecker getItpExprTraceChecker( - final Expr init, - final Expr target, - final ItpSolver solver - ) { - throw new UnsupportedOperationException(String.format("%s domain can't provide trace checker of ItpRefutation", this.getClass().getSimpleName())); + final Expr init, final Expr target, final ItpSolver solver) { + throw new UnsupportedOperationException( + String.format( + "%s domain can't provide trace checker of ItpRefutation", + this.getClass().getSimpleName())); + } + + public + ArgRefiner, XstsAction, P> createRefiner( + ExprTraceChecker traceChecker, + RefutationToPrec refToPrec, + PruneStrategy pruneStrategy, + Logger logger) { + return SingleExprTraceRefiner.create( + traceChecker, JoiningPrecRefiner.create(refToPrec), pruneStrategy, logger); } - - public Refiner, XstsAction, P> - createRefiner( - ExprTraceChecker traceChecker, - RefutationToPrec refToPrec, - PruneStrategy pruneStrategy, - Logger logger - ) { - return SingleExprTraceRefiner.create(traceChecker, JoiningPrecRefiner.create(refToPrec), pruneStrategy, logger); - } - } public enum Search { @@ -165,7 +169,6 @@ public enum Search { Search(final ArgNodeComparators.ArgNodeComparator comparator) { this.comparator = comparator; } - } public enum PredSplit { @@ -196,7 +199,6 @@ public enum InitPrec { InitPrec(final XstsInitPrec builder) { this.builder = builder; } - } public enum AutoExpl { @@ -214,7 +216,8 @@ public enum AutoExpl { } public enum OptimizeStmts { - ON, OFF + ON, + OFF } private Logger logger = NullLogger.getInstance(); @@ -230,8 +233,11 @@ public enum OptimizeStmts { private OptimizeStmts optimizeStmts = OptimizeStmts.ON; private AutoExpl autoExpl = AutoExpl.NEWOPERANDS; - public XstsConfigBuilder(final Domain domain, final Refinement refinement, - final SolverFactory abstractionSolverFactory, final SolverFactory refinementSolverFactory) { + public XstsConfigBuilder( + final Domain domain, + final Refinement refinement, + final SolverFactory abstractionSolverFactory, + final SolverFactory refinementSolverFactory) { this.domain = domain; this.refinement = refinement; this.abstractionSolverFactory = abstractionSolverFactory; @@ -282,12 +288,15 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { if (domain == Domain.EXPL) { return (new ExplStrategy(xsts)).buildConfig(); } - if (domain == Domain.PRED_BOOL || domain == Domain.PRED_CART + if (domain == Domain.PRED_BOOL + || domain == Domain.PRED_CART || domain == Domain.PRED_SPLIT) { return (new PredStrategy(xsts)).buildConfig(); } - if (domain == Domain.EXPL_PRED_BOOL || domain == Domain.EXPL_PRED_CART - || domain == Domain.EXPL_PRED_SPLIT || domain == Domain.EXPL_PRED_COMBINED) { + if (domain == Domain.EXPL_PRED_BOOL + || domain == Domain.EXPL_PRED_CART + || domain == Domain.EXPL_PRED_SPLIT + || domain == Domain.EXPL_PRED_COMBINED) { return (new ProdStrategy(xsts)).buildConfig(); } throw new UnsupportedOperationException(domain + " domain is not supported."); @@ -295,15 +304,26 @@ public XstsConfigBuilder autoExpl(final AutoExpl autoExpl) { public abstract class BuilderStrategy { - protected static final String UNSUPPORTED_CONFIG_VALUE = "Builder strategy %s does not support configuration value %s as %s"; + protected static final String UNSUPPORTED_CONFIG_VALUE = + "Builder strategy %s does not support configuration value %s as %s"; protected final XSTS xsts; protected final Solver abstractionSolver; protected final Expr negProp; @SuppressWarnings("java:S1699") protected BuilderStrategy(XSTS xsts) { - checkState(getSupportedDomains().contains(domain), UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), domain, "domain"); - checkState(getSupportedRefinements().contains(refinement), UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), refinement, "refinement"); + checkState( + getSupportedDomains().contains(domain), + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + domain, + "domain"); + checkState( + getSupportedRefinements().contains(refinement), + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + refinement, + "refinement"); this.xsts = xsts; abstractionSolver = abstractionSolverFactory.createSolver(); negProp = Not(xsts.getProp()); @@ -336,7 +356,7 @@ public XstsAnalysis getAnalysis() { public abstract RefutationToPrec getItpRefToPrec(); - public Refiner, XstsAction, P> getRefiner() { + public ArgRefiner, XstsAction, P> getRefiner() { return refinement.createRefiner( refinement.getItpExprTraceChecker( xsts.getInitFormula(), @@ -353,22 +373,22 @@ XstsConfig, XstsAction, P> buildConfig() { final LTS, XstsAction> lts = getLts(); final Predicate> target = getPredicate(); final Analysis, XstsAction, P> analysis = getAnalysis(); - final ArgBuilder, XstsAction, P> argBuilder = ArgBuilder.create( - lts, analysis, target, - true); - final Abstractor, XstsAction, P> abstractor = BasicAbstractor.builder( - argBuilder) - .waitlist(PriorityWaitlist.create(search.comparator)) - .stopCriterion(refinement.getStopCriterion()) - .logger(logger).build(); - final Refiner, XstsAction, P> refiner = getRefiner(); - final SafetyChecker, XstsAction>, Trace, XstsAction>, P> checker = CegarChecker.create( - abstractor, refiner, - logger); + final ArgBuilder, XstsAction, P> argBuilder = + ArgBuilder.create(lts, analysis, target, true); + final ArgAbstractor, XstsAction, P> abstractor = + BasicArgAbstractor.builder(argBuilder) + .waitlist(PriorityWaitlist.create(search.comparator)) + .stopCriterion(refinement.getStopCriterion()) + .logger(logger) + .build(); + final ArgRefiner, XstsAction, P> refiner = getRefiner(); + final SafetyChecker, XstsAction>, Trace, XstsAction>, P> + checker = ArgCegarChecker.create(abstractor, refiner, logger); return XstsConfig.create(checker, getInitPrec()); } - public MultiAnalysisSide, S, XstsState, XstsAction, P, UnitPrec> getMultiSide() { + public MultiAnalysisSide, S, XstsState, XstsAction, P, UnitPrec> + getMultiSide() { return new MultiAnalysisSide<>( getAnalysis(), XstsControlInitFuncKt.xstsControlInitFunc(), @@ -377,7 +397,6 @@ public MultiAnalysisSide, S, XstsState, XstsAction, P, U XstsCombineExtractUtilsKt::xstsExtractDataState, XstsCombineExtractUtilsKt::xstsExtractControlPrec); } - } public class ExplStrategy extends BuilderStrategy { @@ -394,8 +413,12 @@ Set getSupportedRefinements() { public ExplStrategy(XSTS xsts) { super(xsts); - checkState(domain == Domain.EXPL, - UNSUPPORTED_CONFIG_VALUE, this.getClass().getSimpleName(), domain, "domain"); + checkState( + domain == Domain.EXPL, + UNSUPPORTED_CONFIG_VALUE, + this.getClass().getSimpleName(), + domain, + "domain"); } @Override @@ -419,12 +442,16 @@ public RefutationToPrec getItpRefToPrec() { } @Override - public Refiner, XstsAction, ExplPrec> getRefiner() { + public ArgRefiner, XstsAction, ExplPrec> getRefiner() { if (refinement == Refinement.UNSAT_CORE) { return SingleExprTraceRefiner.create( - ExprTraceUnsatCoreChecker.create(xsts.getInitFormula(), negProp, + ExprTraceUnsatCoreChecker.create( + xsts.getInitFormula(), + negProp, refinementSolverFactory.createUCSolver()), - JoiningPrecRefiner.create(new VarsRefToExplPrec()), pruneStrategy, logger); + JoiningPrecRefiner.create(new VarsRefToExplPrec()), + pruneStrategy, + logger); } return super.getRefiner(); } @@ -433,7 +460,6 @@ public Refiner, XstsAction, ExplPrec> getRefiner() { public ExplPrec getInitPrec() { return initPrec.builder.createExpl(xsts); } - } public class PredStrategy extends BuilderStrategy { @@ -444,13 +470,24 @@ Set getSupportedDomains() { @Override Set getSupportedRefinements() { - return new HashSet<>(List.of(Refinement.FW_BIN_ITP, Refinement.BW_BIN_ITP, Refinement.SEQ_ITP, Refinement.MULTI_SEQ)); + return new HashSet<>( + List.of( + Refinement.FW_BIN_ITP, + Refinement.BW_BIN_ITP, + Refinement.SEQ_ITP, + Refinement.MULTI_SEQ)); } public PredStrategy(XSTS xsts) { super(xsts); - checkState(domain == Domain.PRED_BOOL || domain == Domain.PRED_SPLIT || domain == Domain.PRED_CART, - UNSUPPORTED_CONFIG_VALUE, this.getClass().getSimpleName(), domain, "domain"); + checkState( + domain == Domain.PRED_BOOL + || domain == Domain.PRED_SPLIT + || domain == Domain.PRED_CART, + UNSUPPORTED_CONFIG_VALUE, + this.getClass().getSimpleName(), + domain, + "domain"); } @Override @@ -482,55 +519,80 @@ public PredPrec getInitPrec() { } } - public class ProdStrategy extends BuilderStrategy, Prod2Prec> { + public class ProdStrategy + extends BuilderStrategy< + Prod2State, Prod2Prec> { @Override Set getSupportedDomains() { - return new HashSet<>(List.of(Domain.EXPL_PRED_BOOL, Domain.EXPL_PRED_CART, Domain.EXPL_PRED_SPLIT, Domain.EXPL_PRED_COMBINED)); + return new HashSet<>( + List.of( + Domain.EXPL_PRED_BOOL, + Domain.EXPL_PRED_CART, + Domain.EXPL_PRED_SPLIT, + Domain.EXPL_PRED_COMBINED)); } @Override Set getSupportedRefinements() { - return new HashSet<>(List.of(Refinement.FW_BIN_ITP, Refinement.BW_BIN_ITP, Refinement.SEQ_ITP, Refinement.MULTI_SEQ)); + return new HashSet<>( + List.of( + Refinement.FW_BIN_ITP, + Refinement.BW_BIN_ITP, + Refinement.SEQ_ITP, + Refinement.MULTI_SEQ)); } public ProdStrategy(XSTS xsts) { super(xsts); - checkState(domain == Domain.EXPL_PRED_BOOL || domain == Domain.EXPL_PRED_SPLIT - || domain == Domain.EXPL_PRED_CART || domain == Domain.EXPL_PRED_COMBINED, - UNSUPPORTED_CONFIG_VALUE, this.getClass().getSimpleName(), domain, "domain"); - checkState(refinement != Refinement.UNSAT_CORE, UNSUPPORTED_CONFIG_VALUE, getClass().getSimpleName(), refinement, "refinement"); + checkState( + domain == Domain.EXPL_PRED_BOOL + || domain == Domain.EXPL_PRED_SPLIT + || domain == Domain.EXPL_PRED_CART + || domain == Domain.EXPL_PRED_COMBINED, + UNSUPPORTED_CONFIG_VALUE, + this.getClass().getSimpleName(), + domain, + "domain"); + checkState( + refinement != Refinement.UNSAT_CORE, + UNSUPPORTED_CONFIG_VALUE, + getClass().getSimpleName(), + refinement, + "refinement"); } @Override StmtOptimizer> getLtsOptimizer() { - return Prod2ExplPredStmtOptimizer.create( - ExplStmtOptimizer.getInstance() - ); + return Prod2ExplPredStmtOptimizer.create(ExplStmtOptimizer.getInstance()); } @Override public Predicate>> getPredicate() { - return new XstsStatePredicate<>( - new ExprStatePredicate(negProp, abstractionSolver)); + return new XstsStatePredicate<>(new ExprStatePredicate(negProp, abstractionSolver)); } @Override - public Analysis, StmtAction, Prod2Prec> getDataAnalysis() { - if (domain == Domain.EXPL_PRED_BOOL || domain == Domain.EXPL_PRED_CART + public Analysis, StmtAction, Prod2Prec> + getDataAnalysis() { + if (domain == Domain.EXPL_PRED_BOOL + || domain == Domain.EXPL_PRED_CART || domain == Domain.EXPL_PRED_SPLIT) { - final PredAbstractors.PredAbstractor predAbstractor = domain.predAbstractorFunction.apply(abstractionSolver); + final PredAbstractors.PredAbstractor predAbstractor = + domain.predAbstractorFunction.apply(abstractionSolver); return Prod2Analysis.create( ExplStmtAnalysis.create(abstractionSolver, xsts.getInitFormula(), maxEnum), - PredAnalysis.create(abstractionSolver, predAbstractor, xsts.getInitFormula()), + PredAnalysis.create( + abstractionSolver, predAbstractor, xsts.getInitFormula()), Prod2ExplPredPreStrengtheningOperator.create(), Prod2ExplPredStrengtheningOperator.create(abstractionSolver)); } else { - final Prod2ExplPredAbstractors.Prod2ExplPredAbstractor prodAbstractor = Prod2ExplPredAbstractors.booleanAbstractor( - abstractionSolver); + final Prod2ExplPredAbstractors.Prod2ExplPredAbstractor prodAbstractor = + Prod2ExplPredAbstractors.booleanAbstractor(abstractionSolver); return Prod2ExplPredAnalysis.create( ExplAnalysis.create(abstractionSolver, xsts.getInitFormula()), - PredAnalysis.create(abstractionSolver, + PredAnalysis.create( + abstractionSolver, PredAbstractors.booleanAbstractor(abstractionSolver), xsts.getInitFormula()), Prod2ExplPredStrengtheningOperator.create(abstractionSolver), @@ -548,7 +610,5 @@ public RefutationToPrec, ItpRefutation> getItpRefT public Prod2Prec getInitPrec() { return initPrec.builder.createProd2ExplPred(xsts); } - } - -} \ No newline at end of file +} diff --git a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java index 592abd7ad5..6bbc845a97 100644 --- a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java +++ b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java @@ -31,8 +31,8 @@ import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.unit.UnitAnalysis; import hu.bme.mit.theta.analysis.unit.UnitPrec; import hu.bme.mit.theta.analysis.unit.UnitState; @@ -79,11 +79,11 @@ public void test() throws FileNotFoundException, IOException { lts, analysis, s -> false); - final Abstractor, XtaAction, UnitPrec> abstractor = BasicAbstractor.builder( + final ArgAbstractor, XtaAction, UnitPrec> abstractor = BasicArgAbstractor.builder( argBuilder) .projection(s -> s.getLocs()).build(); - final ARG, XtaAction> arg = abstractor.createArg(); + final ARG, XtaAction> arg = abstractor.createWitness(); abstractor.check(arg, UnitPrec.getInstance()); System.out.println( diff --git a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java index 437049b128..111e451934 100644 --- a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java +++ b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java @@ -32,8 +32,8 @@ import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; -import hu.bme.mit.theta.analysis.algorithm.cegar.Abstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.expl.ExplState; import hu.bme.mit.theta.analysis.impl.PrecMappingAnalysis; import hu.bme.mit.theta.analysis.prod2.Prod2Analysis; @@ -91,10 +91,10 @@ public void test() throws FileNotFoundException, IOException { final ArgBuilder>, XtaAction, ZonePrec> argBuilder = ArgBuilder .create(lts, analysis, s -> false); - final Abstractor>, XtaAction, ZonePrec> abstractor = BasicAbstractor + final ArgAbstractor>, XtaAction, ZonePrec> abstractor = BasicArgAbstractor .builder(argBuilder).projection(s -> s.getLocs()).build(); - final ARG>, XtaAction> arg = abstractor.createArg(); + final ARG>, XtaAction> arg = abstractor.createWitness(); abstractor.check(arg, prec); System.out.println(arg.getNodes().collect(Collectors.toSet())); From ad7ff95d0e7afadb9921bb67b903c095dc213582 Mon Sep 17 00:00:00 2001 From: RipplB Date: Sat, 12 Oct 2024 08:33:57 +0200 Subject: [PATCH 02/21] Rename Witness to Proof --- .../impact/CfaPredImpactCheckerTest.java | 45 +- .../java/hu/bme/mit/theta/cfa/cli/CfaCli.java | 217 +++--- .../mit/theta/analysis/algorithm/Checker.java | 5 +- .../{EmptyWitness.java => EmptyProof.java} | 10 +- .../algorithm/{Witness.java => Proof.java} | 3 +- .../mit/theta/analysis/algorithm/Result.java | 5 +- .../analysis/algorithm/SafetyChecker.java | 12 +- .../analysis/algorithm/SafetyResult.java | 85 +-- .../mit/theta/analysis/algorithm/arg/ARG.java | 74 +-- .../algorithm/bounded/BoundedChecker.kt | 405 ++++++------ .../analysis/algorithm/cegar/Abstractor.java | 21 +- .../algorithm/cegar/BasicArgAbstractor.java | 47 +- .../algorithm/cegar/CegarChecker.java | 50 +- .../analysis/algorithm/cegar/Refiner.java | 6 +- .../analysis/algorithm/chc/HornChecker.kt | 83 +-- .../mcm/analysis/FiniteStateChecker.kt | 91 ++- .../analysis/algorithm/mdd/MddChecker.java | 163 +++-- .../mdd/{MddWitness.java => MddProof.java} | 10 +- .../theta/analysis/utils/ArgVisualizer.java | 97 ++- ...ssVisualizer.java => ProofVisualizer.java} | 8 +- .../algorithm/mdd/MddCheckerTest.java | 159 +++-- .../theta/grammar/gson/SafetyResultAdapter.kt | 114 ++-- .../mit/theta/sts/analysis/StsExplTest.java | 85 ++- .../theta/sts/analysis/StsMddCheckerTest.java | 93 ++- .../mit/theta/sts/analysis/StsPredTest.java | 89 ++- .../java/hu/bme/mit/theta/sts/cli/StsCli.java | 187 ++++-- .../theta/xcfa/analysis/oc/XcfaOcChecker.kt | 615 +++++++++--------- .../bme/mit/theta/xcfa/cli/ExecuteConfig.kt | 588 +++++++++-------- .../cli/checkers/ConfigToBoundedChecker.kt | 63 +- .../xcfa/cli/checkers/ConfigToCegarChecker.kt | 214 +++--- .../xcfa/cli/checkers/ConfigToHornChecker.kt | 52 +- .../xcfa/cli/checkers/ConfigToOcChecker.kt | 30 +- .../xcfa/cli/checkers/InProcessChecker.kt | 250 +++---- .../mit/theta/xcfa/cli/XcfaCliProofTest.kt | 136 ++++ .../mit/theta/xcfa/cli/XcfaCliWitnessTest.kt | 130 ---- .../xsts/analysis/mdd/XstsMddChecker.java | 157 +++-- .../xsts/analysis/XstsMddCheckerTest.java | 215 +++--- .../bme/mit/theta/xsts/cli/XstsCliBounded.kt | 168 +++-- .../hu/bme/mit/theta/xsts/cli/XstsCliCegar.kt | 144 ++-- .../hu/bme/mit/theta/xsts/cli/XstsCliMdd.kt | 98 ++- .../xta/analysis/LazyXtaCheckerTest.java | 60 +- .../theta/xta/analysis/XtaAnalysisTest.java | 67 +- .../xta/analysis/XtaZoneAnalysisTest.java | 75 +-- .../java/hu/bme/mit/theta/xta/cli/XtaCli.java | 77 ++- 44 files changed, 2904 insertions(+), 2399 deletions(-) rename subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/{EmptyWitness.java => EmptyProof.java} (78%) rename subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/{Witness.java => Proof.java} (95%) rename subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/{MddWitness.java => MddProof.java} (81%) rename subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/{WitnessVisualizer.java => ProofVisualizer.java} (83%) create mode 100644 subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt delete mode 100644 subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliWitnessTest.kt diff --git a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java index 4204a3785d..111600967f 100644 --- a/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java +++ b/subprojects/cfa/cfa-analysis/src/test/java/hu/bme/mit/theta/cfa/analysis/impact/CfaPredImpactCheckerTest.java @@ -17,60 +17,65 @@ import static org.junit.Assert.assertTrue; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; - import hu.bme.mit.theta.analysis.Trace; import hu.bme.mit.theta.analysis.algorithm.SafetyResult; -import hu.bme.mit.theta.analysis.pred.PredState; -import hu.bme.mit.theta.cfa.analysis.CfaAction; -import hu.bme.mit.theta.cfa.analysis.CfaState; -import hu.bme.mit.theta.solver.Solver; -import org.junit.Test; - import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgChecker; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; +import hu.bme.mit.theta.analysis.pred.PredState; import hu.bme.mit.theta.analysis.unit.UnitPrec; import hu.bme.mit.theta.analysis.utils.ArgVisualizer; import hu.bme.mit.theta.cfa.CFA; +import hu.bme.mit.theta.cfa.analysis.CfaAction; +import hu.bme.mit.theta.cfa.analysis.CfaState; import hu.bme.mit.theta.cfa.analysis.lts.CfaLbeLts; import hu.bme.mit.theta.cfa.dsl.CfaDslManager; import hu.bme.mit.theta.common.visualization.writer.GraphvizWriter; import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import org.junit.Test; public final class CfaPredImpactCheckerTest { @Test public void test() throws FileNotFoundException, IOException { // Arrange - final CFA cfa = CfaDslManager.createCfa( - new FileInputStream("src/test/resources/counter5_true.cfa")); + final CFA cfa = + CfaDslManager.createCfa( + new FileInputStream("src/test/resources/counter5_true.cfa")); final Solver abstractionSolver = Z3LegacySolverFactory.getInstance().createSolver(); final ItpSolver refinementSolver = Z3LegacySolverFactory.getInstance().createItpSolver(); - final PredImpactChecker checker = PredImpactChecker.create( - CfaLbeLts.of(cfa.getErrorLoc().get()), cfa.getInitLoc(), - l -> l.equals(cfa.getErrorLoc().get()), abstractionSolver, refinementSolver); + final PredImpactChecker checker = + PredImpactChecker.create( + CfaLbeLts.of(cfa.getErrorLoc().get()), + cfa.getInitLoc(), + l -> l.equals(cfa.getErrorLoc().get()), + abstractionSolver, + refinementSolver); // Act - final SafetyResult, CfaAction>, Trace, CfaAction>> status = checker.check( - UnitPrec.getInstance()); + final SafetyResult< + ARG, CfaAction>, Trace, CfaAction>> + status = checker.check(UnitPrec.getInstance()); // Assert assertTrue(status.isSafe()); - final ARG arg = status.getWitness(); + final ARG arg = status.getProof(); arg.minimize(); final ArgChecker argChecker = ArgChecker.create(abstractionSolver); assertTrue(argChecker.isWellLabeled(arg)); System.out.println( - GraphvizWriter.getInstance().writeString(ArgVisualizer.getDefault().visualize(arg))); + GraphvizWriter.getInstance() + .writeString(ArgVisualizer.getDefault().visualize(arg))); } -} \ No newline at end of file +} diff --git a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java index 024911743e..eda6c15702 100644 --- a/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java +++ b/subprojects/cfa/cfa-cli/src/main/java/hu/bme/mit/theta/cfa/cli/CfaCli.java @@ -15,6 +15,8 @@ */ package hu.bme.mit.theta.cfa.cli; +import static com.google.common.base.Preconditions.checkNotNull; + import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; @@ -27,8 +29,6 @@ import hu.bme.mit.theta.analysis.algorithm.bounded.MonolithicExpr; import hu.bme.mit.theta.analysis.algorithm.cegar.CegarStatistics; import hu.bme.mit.theta.analysis.expl.ExplState; -import hu.bme.mit.theta.analysis.expr.ExprAction; -import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.analysis.expr.refinement.PruneStrategy; import hu.bme.mit.theta.cfa.CFA; import hu.bme.mit.theta.cfa.analysis.CfaAction; @@ -37,14 +37,7 @@ import hu.bme.mit.theta.cfa.analysis.CfaTraceConcretizer; import hu.bme.mit.theta.cfa.analysis.config.CfaConfig; import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Algorithm; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Domain; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Encoding; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.InitPrec; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.PrecGranularity; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.PredSplit; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Refinement; -import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.Search; +import hu.bme.mit.theta.cfa.analysis.config.CfaConfigBuilder.*; import hu.bme.mit.theta.cfa.analysis.utils.CfaVisualizer; import hu.bme.mit.theta.cfa.dsl.CfaDslManager; import hu.bme.mit.theta.common.CliUtils; @@ -62,28 +55,21 @@ import hu.bme.mit.theta.solver.smtlib.SmtLibSolverManager; import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory; import hu.bme.mit.theta.solver.z3legacy.Z3SolverManager; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.io.*; import java.nio.file.Path; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * A command line interface for running a CEGAR configuration on a CFA. - */ +/** A command line interface for running a CEGAR configuration on a CFA. */ public class CfaCli { private static final String JAR_NAME = "theta-cfa-cli.jar"; private final String[] args; private final TableWriter writer; - @Parameter(names = {"--algorithm"}, description = "Algorithm") + + @Parameter( + names = {"--algorithm"}, + description = "Algorithm") Algorithm algorithm = Algorithm.CEGAR; @Parameter(names = "--domain", description = "Abstract domain") @@ -95,16 +81,34 @@ public class CfaCli { @Parameter(names = "--search", description = "Search strategy") Search search = Search.BFS; - @Parameter(names = "--predsplit", description = "Predicate splitting (for predicate abstraction)") + @Parameter( + names = "--predsplit", + description = "Predicate splitting (for predicate abstraction)") PredSplit predSplit = PredSplit.WHOLE; - @Parameter(names = "--solver", description = "Sets the underlying SMT solver to use for both the abstraction and the refinement process. Enter in format :, see theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy z3 solver.") + @Parameter( + names = "--solver", + description = + "Sets the underlying SMT solver to use for both the abstraction and the" + + " refinement process. Enter in format :, see" + + " theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy" + + " z3 solver.") String solver = "Z3"; - @Parameter(names = "--abstraction-solver", description = "Sets the underlying SMT solver to use for the abstraction process. Enter in format :, see theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy z3 solver.") + @Parameter( + names = "--abstraction-solver", + description = + "Sets the underlying SMT solver to use for the abstraction process. Enter in" + + " format :, see theta-smtlib-cli.jar for" + + " more details. Enter \"Z3\" to use the legacy z3 solver.") String abstractionSolver; - @Parameter(names = "--refinement-solver", description = "Sets the underlying SMT solver to use for the refinement process. Enter in format :, see theta-smtlib-cli.jar for more details. Enter \"Z3\" to use the legacy z3 solver.") + @Parameter( + names = "--refinement-solver", + description = + "Sets the underlying SMT solver to use for the refinement process. Enter in" + + " format :, see theta-smtlib-cli.jar for" + + " more details. Enter \"Z3\" to use the legacy z3 solver.") String refinementSolver; @Parameter(names = "--home", description = "The path of the solver registry") @@ -122,13 +126,17 @@ public class CfaCli { @Parameter(names = "--encoding", description = "Block encoding") Encoding encoding = Encoding.LBE; - @Parameter(names = "--maxenum", description = "Maximal number of explicitly enumerated successors (0: unlimited)") + @Parameter( + names = "--maxenum", + description = "Maximal number of explicitly enumerated successors (0: unlimited)") Integer maxEnum = 10; @Parameter(names = "--initprec", description = "Initial precision of abstraction") InitPrec initPrec = InitPrec.EMPTY; - @Parameter(names = "--prunestrategy", description = "Strategy for pruning the ARG after refinement") + @Parameter( + names = "--prunestrategy", + description = "Strategy for pruning the ARG after refinement") PruneStrategy pruneStrategy = PruneStrategy.LAZY; @Parameter(names = "--loglevel", description = "Detailedness of logging") @@ -140,13 +148,20 @@ public class CfaCli { @Parameter(names = "--cex", description = "Write concrete counterexample to a file") String cexfile = null; - @Parameter(names = "--header", description = "Print only a header (for benchmarks)", help = true) + @Parameter( + names = "--header", + description = "Print only a header (for benchmarks)", + help = true) boolean headerOnly = false; - @Parameter(names = "--visualize", description = "Visualize CFA to this file without running the algorithm") + @Parameter( + names = "--visualize", + description = "Visualize CFA to this file without running the algorithm") String visualize = null; - @Parameter(names = "--metrics", description = "Print metrics about the CFA without running the algorithm") + @Parameter( + names = "--metrics", + description = "Print metrics about the CFA without running the algorithm") boolean metrics = false; @Parameter(names = "--stacktrace", description = "Print full stack trace in case of exception") @@ -241,13 +256,19 @@ private void run() { final SafetyResult> status; if (algorithm == Algorithm.CEGAR) { - final CfaConfig configuration = buildConfiguration(cfa, errLoc, abstractionSolverFactory, refinementSolverFactory); + final CfaConfig configuration = + buildConfiguration( + cfa, errLoc, abstractionSolverFactory, refinementSolverFactory); status = check(configuration); - } else if (algorithm == Algorithm.BMC || algorithm == Algorithm.KINDUCTION || algorithm == Algorithm.IMC) { - final BoundedChecker checker = buildBoundedChecker(cfa, abstractionSolverFactory); + } else if (algorithm == Algorithm.BMC + || algorithm == Algorithm.KINDUCTION + || algorithm == Algorithm.IMC) { + final BoundedChecker checker = + buildBoundedChecker(cfa, abstractionSolverFactory); status = checker.check(null); } else { - throw new UnsupportedOperationException("Algorithm " + algorithm + " not supported"); + throw new UnsupportedOperationException( + "Algorithm " + algorithm + " not supported"); } sw.stop(); @@ -262,8 +283,18 @@ private void run() { } private void printHeader() { - Stream.of("Result", "TimeMs", "AlgoTimeMs", "AbsTimeMs", "RefTimeMs", "Iterations", - "ArgSize", "ArgDepth", "ArgMeanBranchFactor", "CexLen").forEach(writer::cell); + Stream.of( + "Result", + "TimeMs", + "AlgoTimeMs", + "AbsTimeMs", + "RefTimeMs", + "Iterations", + "ArgSize", + "ArgDepth", + "ArgMeanBranchFactor", + "CexLen") + .forEach(writer::cell); writer.newRow(); } @@ -277,67 +308,89 @@ private CFA loadModel() throws Exception { } } - private CfaConfig buildConfiguration(final CFA cfa, final CFA.Loc errLoc, - final SolverFactory abstractionSolverFactory, final SolverFactory refinementSolverFactory) + private CfaConfig buildConfiguration( + final CFA cfa, + final CFA.Loc errLoc, + final SolverFactory abstractionSolverFactory, + final SolverFactory refinementSolverFactory) throws Exception { try { - return new CfaConfigBuilder(domain, refinement, abstractionSolverFactory, - refinementSolverFactory) - .precGranularity(precGranularity).search(search) - .predSplit(predSplit).encoding(encoding).maxEnum(maxEnum).initPrec(initPrec) - .pruneStrategy(pruneStrategy).logger(logger).build(cfa, errLoc); + return new CfaConfigBuilder( + domain, refinement, abstractionSolverFactory, refinementSolverFactory) + .precGranularity(precGranularity) + .search(search) + .predSplit(predSplit) + .encoding(encoding) + .maxEnum(maxEnum) + .initPrec(initPrec) + .pruneStrategy(pruneStrategy) + .logger(logger) + .build(cfa, errLoc); } catch (final Exception ex) { throw new Exception("Could not create configuration: " + ex.getMessage(), ex); } } - private BoundedChecker buildBoundedChecker(final CFA cfa, final SolverFactory abstractionSolverFactory) { + private BoundedChecker buildBoundedChecker( + final CFA cfa, final SolverFactory abstractionSolverFactory) { final MonolithicExpr monolithicExpr = CfaToMonolithicExprKt.toMonolithicExpr(cfa); final BoundedChecker checker; switch (algorithm) { - case BMC -> checker = BoundedCheckerBuilderKt.buildBMC( - monolithicExpr, - abstractionSolverFactory.createSolver(), - val -> CfaToMonolithicExprKt.valToState(cfa, val), - (val1, val2) -> CfaToMonolithicExprKt.valToAction(cfa, val1, val2), - logger - ); - case KINDUCTION -> checker = BoundedCheckerBuilderKt.buildKIND( - monolithicExpr, - abstractionSolverFactory.createSolver(), - abstractionSolverFactory.createSolver(), - val -> CfaToMonolithicExprKt.valToState(cfa, val), - (val1, val2) -> CfaToMonolithicExprKt.valToAction(cfa, val1, val2), - logger - ); - case IMC -> checker = BoundedCheckerBuilderKt.buildIMC( - monolithicExpr, - abstractionSolverFactory.createSolver(), - abstractionSolverFactory.createItpSolver(), - val -> CfaToMonolithicExprKt.valToState(cfa, val), - (val1, val2) -> CfaToMonolithicExprKt.valToAction(cfa, val1, val2), - logger - ); + case BMC -> + checker = + BoundedCheckerBuilderKt.buildBMC( + monolithicExpr, + abstractionSolverFactory.createSolver(), + val -> CfaToMonolithicExprKt.valToState(cfa, val), + (val1, val2) -> + CfaToMonolithicExprKt.valToAction(cfa, val1, val2), + logger); + case KINDUCTION -> + checker = + BoundedCheckerBuilderKt.buildKIND( + monolithicExpr, + abstractionSolverFactory.createSolver(), + abstractionSolverFactory.createSolver(), + val -> CfaToMonolithicExprKt.valToState(cfa, val), + (val1, val2) -> + CfaToMonolithicExprKt.valToAction(cfa, val1, val2), + logger); + case IMC -> + checker = + BoundedCheckerBuilderKt.buildIMC( + monolithicExpr, + abstractionSolverFactory.createSolver(), + abstractionSolverFactory.createItpSolver(), + val -> CfaToMonolithicExprKt.valToState(cfa, val), + (val1, val2) -> + CfaToMonolithicExprKt.valToAction(cfa, val1, val2), + logger); default -> - throw new UnsupportedOperationException("Algorithm " + algorithm + " not supported"); + throw new UnsupportedOperationException( + "Algorithm " + algorithm + " not supported"); } return checker; } - private SafetyResult, ? extends Trace> check(CfaConfig configuration) throws Exception { + private SafetyResult, ? extends Trace> check( + CfaConfig configuration) throws Exception { try { return configuration.check(); } catch (final Exception ex) { String message = ex.getMessage() == null ? "(no message)" : ex.getMessage(); throw new Exception( - "Error while running algorithm: " + ex.getClass().getSimpleName() + " " + message, + "Error while running algorithm: " + + ex.getClass().getSimpleName() + + " " + + message, ex); } } - private void printResult(final SafetyResult> status, final long totalTimeMs) { - final CegarStatistics stats = (CegarStatistics) - status.getStats().orElse(new CegarStatistics(0, 0, 0, 0)); + private void printResult( + final SafetyResult> status, final long totalTimeMs) { + final CegarStatistics stats = + (CegarStatistics) status.getStats().orElse(new CegarStatistics(0, 0, 0, 0)); if (benchmarkMode) { writer.cell(status.isSafe()); writer.cell(totalTimeMs); @@ -345,7 +398,7 @@ private void printResult(final SafetyResult> status, fi writer.cell(stats.getAbstractorTimeMs()); writer.cell(stats.getRefinerTimeMs()); writer.cell(stats.getIterations()); - if (status.getWitness() instanceof ARG arg) { + if (status.getProof() instanceof ARG arg) { writer.cell(arg.size()); writer.cell(arg.getDepth()); writer.cell(arg.getMeanBranchingFactor()); @@ -369,7 +422,10 @@ private void printError(final Throwable ex) { writer.cell("[EX] " + ex.getClass().getSimpleName() + ": " + message); writer.newRow(); } else { - logger.write(Level.RESULT, "%s occurred, message: %s%n", ex.getClass().getSimpleName(), + logger.write( + Level.RESULT, + "%s occurred, message: %s%n", + ex.getClass().getSimpleName(), message); if (stacktrace) { final StringWriter errors = new StringWriter(); @@ -382,9 +438,10 @@ private void printError(final Throwable ex) { } private void writeCex(final SafetyResult.Unsafe status) throws FileNotFoundException { - @SuppressWarnings("unchecked") final Trace, CfaAction> trace = (Trace, CfaAction>) status.getCex(); - final Trace, CfaAction> concrTrace = CfaTraceConcretizer.concretize( - trace, Z3LegacySolverFactory.getInstance()); + @SuppressWarnings("unchecked") + final Trace, CfaAction> trace = (Trace, CfaAction>) status.getCex(); + final Trace, CfaAction> concrTrace = + CfaTraceConcretizer.concretize(trace, Z3LegacySolverFactory.getInstance()); final File file = new File(cexfile); PrintWriter printWriter = null; try { diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Checker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Checker.java index e1a86bee69..afed36eab9 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Checker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Checker.java @@ -15,8 +15,7 @@ */ package hu.bme.mit.theta.analysis.algorithm; -public interface Checker { - - Result check(I input); +public interface Checker { + Result check(I input); } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/EmptyWitness.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/EmptyProof.java similarity index 78% rename from subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/EmptyWitness.java rename to subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/EmptyProof.java index 49794dd84e..1c8d976149 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/EmptyWitness.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/EmptyProof.java @@ -15,15 +15,13 @@ */ package hu.bme.mit.theta.analysis.algorithm; -public class EmptyWitness implements Witness { +public class EmptyProof implements Proof { - private final static EmptyWitness empty = new EmptyWitness(); + private static final EmptyProof empty = new EmptyProof(); - private EmptyWitness() { - } + private EmptyProof() {} - public static EmptyWitness getInstance() { + public static EmptyProof getInstance() { return empty; } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Witness.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Proof.java similarity index 95% rename from subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Witness.java rename to subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Proof.java index ff6157e1e3..3668ab6315 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Witness.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Proof.java @@ -15,5 +15,4 @@ */ package hu.bme.mit.theta.analysis.algorithm; -public interface Witness { -} +public interface Proof {} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Result.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Result.java index 0c81bf5836..438edde295 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Result.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/Result.java @@ -17,10 +17,9 @@ import java.util.Optional; -public interface Result { +public interface Result { - W getWitness(); + Pr getProof(); Optional getStats(); - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyChecker.java index 4f13fac64c..c716c1dc24 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyChecker.java @@ -15,19 +15,15 @@ */ package hu.bme.mit.theta.analysis.algorithm; -import hu.bme.mit.theta.analysis.*; -import hu.bme.mit.theta.analysis.algorithm.Checker; -import hu.bme.mit.theta.analysis.algorithm.SafetyResult; -import hu.bme.mit.theta.analysis.algorithm.arg.ARG; +import hu.bme.mit.theta.analysis.Cex; @FunctionalInterface -public interface SafetyChecker extends Checker { +public interface SafetyChecker extends Checker { @Override - SafetyResult check(final I input); + SafetyResult check(final I input); - default SafetyResult check() { + default SafetyResult check() { return check(null); } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyResult.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyResult.java index dfd812ebea..0862dc3079 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyResult.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/SafetyResult.java @@ -15,30 +15,29 @@ */ package hu.bme.mit.theta.analysis.algorithm; +import static com.google.common.base.Preconditions.checkNotNull; + import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.common.Utils; - import java.util.Optional; -import static com.google.common.base.Preconditions.checkNotNull; - -public abstract class SafetyResult implements Result { - private final W witness; +public abstract class SafetyResult implements Result { + private final Pr proof; private final Optional stats; - private SafetyResult(final W witness, final Optional stats) { - this.witness = checkNotNull(witness); + private SafetyResult(final Pr proof, final Optional stats) { + this.proof = checkNotNull(proof); this.stats = checkNotNull(stats); } private SafetyResult() { - this.witness = null; + this.proof = null; this.stats = Optional.empty(); } @Override - public W getWitness() { - return witness; + public Pr getProof() { + return proof; } @Override @@ -46,28 +45,30 @@ public Optional getStats() { return stats; } - public static Safe safe(final W witness) { + public static Safe safe(final Pr witness) { return new Safe<>(witness, Optional.empty()); } - public static Unsafe unsafe(final C cex, final W witness) { + public static Unsafe unsafe( + final C cex, final Pr witness) { return new Unsafe<>(cex, witness, Optional.empty()); } - public static Unknown unknown() { + public static Unknown unknown() { return new Unknown<>(); } - public static Safe safe(final W witness, final Statistics stats) { + public static Safe safe( + final Pr witness, final Statistics stats) { return new Safe<>(witness, Optional.of(stats)); } - public static Unsafe unsafe(final C cex, final W witness, - final Statistics stats) { + public static Unsafe unsafe( + final C cex, final Pr witness, final Statistics stats) { return new Unsafe<>(cex, witness, Optional.of(stats)); } - public static Unknown unknown(final Statistics stats) { + public static Unknown unknown(final Statistics stats) { return new Unknown<>(Optional.of(stats)); } @@ -75,15 +76,15 @@ public static Unknown unknown(final Sta public abstract boolean isUnsafe(); - public abstract Safe asSafe(); + public abstract Safe asSafe(); - public abstract Unsafe asUnsafe(); + public abstract Unsafe asUnsafe(); //// - public static final class Safe extends SafetyResult { - private Safe(final W witness, final Optional stats) { - super(witness, stats); + public static final class Safe extends SafetyResult { + private Safe(final Pr proof, final Optional stats) { + super(proof, stats); } @Override @@ -97,28 +98,32 @@ public boolean isUnsafe() { } @Override - public Safe asSafe() { + public Safe asSafe() { return this; } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { throw new ClassCastException( - "Cannot cast " + Safe.class.getSimpleName() + " to " + Unsafe.class.getSimpleName()); + "Cannot cast " + + Safe.class.getSimpleName() + + " to " + + Unsafe.class.getSimpleName()); } @Override public String toString() { - return Utils.lispStringBuilder(SafetyResult.class.getSimpleName()).add(Safe.class.getSimpleName()) + return Utils.lispStringBuilder(SafetyResult.class.getSimpleName()) + .add(Safe.class.getSimpleName()) .toString(); } } - public static final class Unsafe extends SafetyResult { + public static final class Unsafe extends SafetyResult { private final C cex; - private Unsafe(final C cex, final W witness, final Optional stats) { - super(witness, stats); + private Unsafe(final C cex, final Pr proof, final Optional stats) { + super(proof, stats); this.cex = checkNotNull(cex); } @@ -137,24 +142,29 @@ public boolean isUnsafe() { } @Override - public Safe asSafe() { + public Safe asSafe() { throw new ClassCastException( - "Cannot cast " + Unsafe.class.getSimpleName() + " to " + Safe.class.getSimpleName()); + "Cannot cast " + + Unsafe.class.getSimpleName() + + " to " + + Safe.class.getSimpleName()); } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { return this; } @Override public String toString() { - return Utils.lispStringBuilder(SafetyResult.class.getSimpleName()).add(Unsafe.class.getSimpleName()) - .add("Trace length: " + cex.length()).toString(); + return Utils.lispStringBuilder(SafetyResult.class.getSimpleName()) + .add(Unsafe.class.getSimpleName()) + .add("Trace length: " + cex.length()) + .toString(); } } - public static final class Unknown extends SafetyResult { + public static final class Unknown extends SafetyResult { public Unknown() { super(); @@ -175,12 +185,12 @@ public boolean isUnsafe() { } @Override - public Safe asSafe() { + public Safe asSafe() { return null; } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { return null; } @@ -191,5 +201,4 @@ public String toString() { .toString(); } } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/arg/ARG.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/arg/ARG.java index b43fb37e35..9f2b3c3ae0 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/arg/ARG.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/arg/ARG.java @@ -15,28 +15,22 @@ */ package hu.bme.mit.theta.analysis.algorithm.arg; +import static com.google.common.base.Preconditions.*; +import static java.util.stream.Collectors.toList; + import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.PartialOrd; import hu.bme.mit.theta.analysis.State; -import hu.bme.mit.theta.analysis.algorithm.Witness; +import hu.bme.mit.theta.analysis.algorithm.Proof; import hu.bme.mit.theta.analysis.algorithm.arg.debug.ARGWebDebugger; import hu.bme.mit.theta.common.container.Containers; - import java.util.Collection; import java.util.Optional; import java.util.OptionalInt; import java.util.stream.Stream; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static java.util.stream.Collectors.toList; - -/** - * Represents an abstract reachability graph (ARG). See the related class - * ArgBuilder. - */ -public final class ARG implements Witness { +/** Represents an abstract reachability graph (ARG). See the related class ArgBuilder. */ +public final class ARG implements Proof { private final Collection> initNodes; public boolean initialized; // Set by ArgBuilder @@ -49,7 +43,8 @@ private ARG(final PartialOrd partialOrd) { this.initialized = false; } - public static ARG create(final PartialOrd partialOrd) { + public static ARG create( + final PartialOrd partialOrd) { return new ARG<>(partialOrd); } @@ -75,7 +70,6 @@ public Stream> getIncompleteNodes() { return getInitNodes().flatMap(ArgNode::unexcludedDescendants).filter(n -> !n.isExpanded()); } - PartialOrd getPartialOrd() { return partialOrd; } @@ -83,24 +77,19 @@ PartialOrd getPartialOrd() { //// /** - * Checks if the ARG is complete, i.e., whether it is initialized and all of - * its nodes are complete. + * Checks if the ARG is complete, i.e., whether it is initialized and all of its nodes are + * complete. */ public boolean isComplete() { return isInitialized() && getNodes().allMatch(ArgNode::isComplete); } - /** - * Checks if the ARG is safe, i.e., whether all of its nodes are safe. - */ + /** Checks if the ARG is safe, i.e., whether all of its nodes are safe. */ public boolean isSafe() { return getNodes().allMatch(ArgNode::isSafe); } - /** - * Checks if the ARG is initialized, i.e., all of its initial nodes are - * present. - */ + /** Checks if the ARG is initialized, i.e., all of its initial nodes are present. */ public boolean isInitialized() { return initialized; } @@ -115,8 +104,8 @@ public ArgNode createInitNode(final S initState, final boolean target) { return initNode; } - public ArgNode createSuccNode(final ArgNode node, final A action, final S succState, - final boolean target) { + public ArgNode createSuccNode( + final ArgNode node, final A action, final S succState, final boolean target) { checkNotNull(node); checkNotNull(action); checkNotNull(succState); @@ -133,7 +122,8 @@ private ArgNode createNode(final S state, final int depth, final boolean t return node; } - private ArgEdge createEdge(final ArgNode source, final A action, final ArgNode target) { + private ArgEdge createEdge( + final ArgNode source, final A action, final ArgNode target) { final ArgEdge edge = new ArgEdge<>(source, action, target); source.outEdges.add(edge); target.inEdge = Optional.of(edge); @@ -141,9 +131,7 @@ private ArgEdge createEdge(final ArgNode source, final A action, fin return edge; } - /** - * Removes a node along with its subtree. - */ + /** Removes a node along with its subtree. */ public void prune(final ArgNode node) { checkNotNull(node); checkArgument(node.arg == this, "Node does not belong to this ARG"); @@ -162,17 +150,13 @@ public void prune(final ArgNode node) { node.descendants().forEach(ArgNode::clearCoveredNodes); } - /** - * Prune the whole ARG, making it uninitialized. - */ + /** Prune the whole ARG, making it uninitialized. */ public void pruneAll() { initNodes.clear(); this.initialized = false; } - /** - * Marks the node for reexpanding without pruning it. - */ + /** Marks the node for reexpanding without pruning it. */ public void markForReExpansion(final ArgNode node) { node.expanded = false; } @@ -192,24 +176,19 @@ private void minimizeSubTree(final ArgNode node) { //// - /** - * Gets all counterexamples, i.e., traces leading to target nodes. - */ + /** Gets all counterexamples, i.e., traces leading to target nodes. */ public Stream> getCexs() { return getUnsafeNodes().map(ArgTrace::to); } - /** - * Gets the size of the ARG, i.e., the number of nodes. - */ + /** Gets the size of the ARG, i.e., the number of nodes. */ public long size() { return getNodes().count(); } /** - * Gets the depth of the ARG, i.e., the maximal depth of its nodes. Depth - * starts (at the initial nodes) from 0. Depth is undefined for an empty - * ARG. + * Gets the depth of the ARG, i.e., the maximal depth of its nodes. Depth starts (at the initial + * nodes) from 0. Depth is undefined for an empty ARG. */ public int getDepth() { final OptionalInt maxOpt = getNodes().mapToInt(ArgNode::getDepth).max(); @@ -217,12 +196,11 @@ public int getDepth() { return maxOpt.getAsInt(); } - /** - * Gets the mean branching factor of the expanded nodes. - */ + /** Gets the mean branching factor of the expanded nodes. */ public double getMeanBranchingFactor() { final Stream> nodesToCalculate = getNodes().filter(ArgNode::isExpanded); - final double mean = nodesToCalculate.mapToDouble(n -> n.getOutEdges().count()).average().orElse(0); + final double mean = + nodesToCalculate.mapToDouble(n -> n.getOutEdges().count()).average().orElse(0); return mean; } } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/bounded/BoundedChecker.kt b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/bounded/BoundedChecker.kt index 72b90fe53f..2c1273f87f 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/bounded/BoundedChecker.kt +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/bounded/BoundedChecker.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.analysis.algorithm.bounded import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.expr.ExprAction @@ -43,228 +42,246 @@ import java.util.* * @param The state type, must inherit from ExprState. * @param The action type, must inherit from StmtAction. * @param monolithicExpr The monolithic expression to be checked - * @param shouldGiveUp A function determining whether to give up checking based on a given iteration count. Use this - * to implement custom timeout or thread interruption checking subroutines. + * @param shouldGiveUp A function determining whether to give up checking based on a given iteration + * count. Use this to implement custom timeout or thread interruption checking subroutines. * @param bmcSolver The solver for bounded model checking. - * @param bmcEnabled A function determining whether bounded model checking is enabled. Cannot be disabled per-iteration. - * Use the capabilities of the lambda parameter to decide on enabledness based on external factors, - * such as available memory or time limit remaining. + * @param bmcEnabled A function determining whether bounded model checking is enabled. Cannot be + * disabled per-iteration. Use the capabilities of the lambda parameter to decide on enabledness + * based on external factors, such as available memory or time limit remaining. * @param lfPathOnly A function determining whether to consider only loop-free paths. * @param itpSolver The solver for interpolation, used in IMC. * @param imcEnabled A function determining whether IMC is enabled. Can be different per-iteration. * @param indSolver The solver for induction checking in KIND. * @param kindEnabled A function determining whether k-induction (KIND) is enabled. - * @param valToState A function mapping valuations to expression states, used to construct a counterexample. - * @param biValToAction A function mapping pairs of valuations to statements, used to construct a counterexample. + * @param valToState A function mapping valuations to expression states, used to construct a + * counterexample. + * @param biValToAction A function mapping pairs of valuations to statements, used to construct a + * counterexample. * @param logger The logger for logging. */ -class BoundedChecker @JvmOverloads constructor( - private val monolithicExpr: MonolithicExpr, - private val shouldGiveUp: (Int) -> Boolean = { false }, - private val bmcSolver: Solver? = null, - private val bmcEnabled: () -> Boolean = { bmcSolver != null }, - private val lfPathOnly: () -> Boolean = { true }, - private val itpSolver: ItpSolver? = null, - private val imcEnabled: (Int) -> Boolean = { itpSolver != null }, - private val indSolver: Solver? = null, - private val kindEnabled: (Int) -> Boolean = { indSolver != null }, - private val valToState: (Valuation) -> S, - private val biValToAction: (Valuation, Valuation) -> A, - private val logger: Logger, -) : SafetyChecker, UnitPrec> { - - private val vars = monolithicExpr.vars() - private val unfoldedInitExpr = PathUtils.unfold(monolithicExpr.initExpr, VarIndexingFactory.indexing(0)) - private val unfoldedPropExpr = { i: VarIndexing -> PathUtils.unfold(monolithicExpr.propExpr, i) } - private val indices = mutableListOf(monolithicExpr.initOffsetIndex) - private val exprs = mutableListOf>() - private var kindLastIterLookup = 0 - private var iteration = 0 - - init { - check(bmcSolver != itpSolver || bmcSolver == null) { "Use distinct solvers for BMC and IMC!" } - check(bmcSolver != indSolver || bmcSolver == null) { "Use distinct solvers for BMC and KInd!" } - check(itpSolver != indSolver || itpSolver == null) { "Use distinct solvers for IMC and KInd!" } - } - - override fun check(prec: UnitPrec?): SafetyResult> { - - iteration = 0 - - val isBmcEnabled = bmcEnabled() // we don't allow per-iteration setting of bmc enabledness - bmcSolver?.add(unfoldedInitExpr) - - while (!shouldGiveUp(iteration)) { - iteration++ - logger.write(Logger.Level.MAINSTEP, "Starting iteration $iteration\n") - - exprs.add(PathUtils.unfold(monolithicExpr.transExpr, indices.last())) - - indices.add(indices.last().add(monolithicExpr.transOffsetIndex)) - - if (isBmcEnabled) { - bmc()?.let { return it } - } +class BoundedChecker +@JvmOverloads +constructor( + private val monolithicExpr: MonolithicExpr, + private val shouldGiveUp: (Int) -> Boolean = { false }, + private val bmcSolver: Solver? = null, + private val bmcEnabled: () -> Boolean = { bmcSolver != null }, + private val lfPathOnly: () -> Boolean = { true }, + private val itpSolver: ItpSolver? = null, + private val imcEnabled: (Int) -> Boolean = { itpSolver != null }, + private val indSolver: Solver? = null, + private val kindEnabled: (Int) -> Boolean = { indSolver != null }, + private val valToState: (Valuation) -> S, + private val biValToAction: (Valuation, Valuation) -> A, + private val logger: Logger, +) : SafetyChecker, UnitPrec> { + + private val vars = monolithicExpr.vars() + private val unfoldedInitExpr = + PathUtils.unfold(monolithicExpr.initExpr, VarIndexingFactory.indexing(0)) + private val unfoldedPropExpr = { i: VarIndexing -> PathUtils.unfold(monolithicExpr.propExpr, i) } + private val indices = mutableListOf(monolithicExpr.initOffsetIndex) + private val exprs = mutableListOf>() + private var kindLastIterLookup = 0 + private var iteration = 0 + + init { + check(bmcSolver != itpSolver || bmcSolver == null) { "Use distinct solvers for BMC and IMC!" } + check(bmcSolver != indSolver || bmcSolver == null) { "Use distinct solvers for BMC and KInd!" } + check(itpSolver != indSolver || itpSolver == null) { "Use distinct solvers for IMC and KInd!" } + } + + override fun check(prec: UnitPrec?): SafetyResult> { + + iteration = 0 + + val isBmcEnabled = bmcEnabled() // we don't allow per-iteration setting of bmc enabledness + bmcSolver?.add(unfoldedInitExpr) + + while (!shouldGiveUp(iteration)) { + iteration++ + logger.write(Logger.Level.MAINSTEP, "Starting iteration $iteration\n") + + exprs.add(PathUtils.unfold(monolithicExpr.transExpr, indices.last())) + + indices.add(indices.last().add(monolithicExpr.transOffsetIndex)) + + if (isBmcEnabled) { + bmc()?.let { + return it + } + } - if (kindEnabled(iteration)) { - if (!isBmcEnabled) { - error("Bad configuration: induction check should always be preceded by a BMC/SAT check") - } - kind()?.let { return it } - kindLastIterLookup = iteration - } + if (kindEnabled(iteration)) { + if (!isBmcEnabled) { + error("Bad configuration: induction check should always be preceded by a BMC/SAT check") + } + kind()?.let { + return it + } + kindLastIterLookup = iteration + } - if (imcEnabled(iteration)) { - itp()?.let { return it } - } + if (imcEnabled(iteration)) { + itp()?.let { + return it } - return SafetyResult.unknown(BoundedStatistics(iteration)) + } } - - private fun bmc(): SafetyResult>? { - val bmcSolver = this.bmcSolver!! - logger.write(Logger.Level.MAINSTEP, "\tStarting BMC\n") - - bmcSolver.add(exprs.last()) - - if (lfPathOnly()) { // indices contains currIndex as last() - for (indexing in indices) { - if (indexing != indices.last()) { - val allVarsSame = And(vars.map { - Eq(PathUtils.unfold(it.ref, indexing), PathUtils.unfold(it.ref, indices.last())) - }) - bmcSolver.add(Not(allVarsSame)) - } - } - - if (bmcSolver.check().isUnsat) { - logger.write(Logger.Level.MAINSTEP, "Safety proven in BMC step\n") - return SafetyResult.safe(EmptyWitness.getInstance(), BoundedStatistics(iteration)) - } + return SafetyResult.unknown(BoundedStatistics(iteration)) + } + + private fun bmc(): SafetyResult>? { + val bmcSolver = this.bmcSolver!! + logger.write(Logger.Level.MAINSTEP, "\tStarting BMC\n") + + bmcSolver.add(exprs.last()) + + if (lfPathOnly()) { // indices contains currIndex as last() + for (indexing in indices) { + if (indexing != indices.last()) { + val allVarsSame = + And( + vars.map { + Eq(PathUtils.unfold(it.ref, indexing), PathUtils.unfold(it.ref, indices.last())) + } + ) + bmcSolver.add(Not(allVarsSame)) } + } - return WithPushPop(bmcSolver).use { - bmcSolver.add(Not(unfoldedPropExpr(indices.last()))) - - if (bmcSolver.check().isSat) { - val trace = getTrace(bmcSolver.model) - logger.write(Logger.Level.MAINSTEP, "CeX found in BMC step (length ${trace.length()})\n") - SafetyResult.unsafe(trace, EmptyWitness.getInstance(), BoundedStatistics(iteration)) - } else null - } + if (bmcSolver.check().isUnsat) { + logger.write(Logger.Level.MAINSTEP, "Safety proven in BMC step\n") + return SafetyResult.safe(EmptyProof.getInstance(), BoundedStatistics(iteration)) + } } - private fun kind(): SafetyResult>? { - val indSolver = this.indSolver!! + return WithPushPop(bmcSolver).use { + bmcSolver.add(Not(unfoldedPropExpr(indices.last()))) - logger.write(Logger.Level.MAINSTEP, "\tStarting k-induction\n") + if (bmcSolver.check().isSat) { + val trace = getTrace(bmcSolver.model) + logger.write(Logger.Level.MAINSTEP, "CeX found in BMC step (length ${trace.length()})\n") + SafetyResult.unsafe(trace, EmptyProof.getInstance(), BoundedStatistics(iteration)) + } else null + } + } - exprs.subList(kindLastIterLookup, exprs.size).forEach { indSolver.add(it) } - indices.subList(kindLastIterLookup, indices.size - 1).forEach { indSolver.add(unfoldedPropExpr(it)) } + private fun kind(): SafetyResult>? { + val indSolver = this.indSolver!! - return WithPushPop(indSolver).use { - indSolver.add(Not(unfoldedPropExpr(indices.last()))) + logger.write(Logger.Level.MAINSTEP, "\tStarting k-induction\n") - if (indSolver.check().isUnsat) { - logger.write(Logger.Level.MAINSTEP, "Safety proven in k-induction step\n") - SafetyResult.safe(EmptyWitness.getInstance(), BoundedStatistics(iteration)) - } else null - } + exprs.subList(kindLastIterLookup, exprs.size).forEach { indSolver.add(it) } + indices.subList(kindLastIterLookup, indices.size - 1).forEach { + indSolver.add(unfoldedPropExpr(it)) } - private fun itp(): SafetyResult>? { - val itpSolver = this.itpSolver!! - logger.write(Logger.Level.MAINSTEP, "\tStarting IMC\n") - - itpSolver.push() - - val a = itpSolver.createMarker() - val b = itpSolver.createMarker() - val pattern = itpSolver.createBinPattern(a, b) - - itpSolver.push() - - itpSolver.add(a, unfoldedInitExpr) - itpSolver.add(a, exprs[0]) - itpSolver.add(b, exprs.subList(1, exprs.size)) - - if (lfPathOnly()) { // indices contains currIndex as last() - itpSolver.push() - for (indexing in indices) { - if (indexing != indices.last()) { - val allVarsSame = And(vars.map { - Eq(PathUtils.unfold(it.ref, indexing), PathUtils.unfold(it.ref, indices.last())) - }) - itpSolver.add(a, Not(allVarsSame)) - } - } - - if (itpSolver.check().isUnsat) { - itpSolver.pop() - itpSolver.pop() - logger.write(Logger.Level.MAINSTEP, "Safety proven in IMC/BMC step\n") - return SafetyResult.safe(EmptyWitness.getInstance(), BoundedStatistics(iteration)) - } - itpSolver.pop() + return WithPushPop(indSolver).use { + indSolver.add(Not(unfoldedPropExpr(indices.last()))) + + if (indSolver.check().isUnsat) { + logger.write(Logger.Level.MAINSTEP, "Safety proven in k-induction step\n") + SafetyResult.safe(EmptyProof.getInstance(), BoundedStatistics(iteration)) + } else null + } + } + + private fun itp(): SafetyResult>? { + val itpSolver = this.itpSolver!! + logger.write(Logger.Level.MAINSTEP, "\tStarting IMC\n") + + itpSolver.push() + + val a = itpSolver.createMarker() + val b = itpSolver.createMarker() + val pattern = itpSolver.createBinPattern(a, b) + + itpSolver.push() + + itpSolver.add(a, unfoldedInitExpr) + itpSolver.add(a, exprs[0]) + itpSolver.add(b, exprs.subList(1, exprs.size)) + + if (lfPathOnly()) { // indices contains currIndex as last() + itpSolver.push() + for (indexing in indices) { + if (indexing != indices.last()) { + val allVarsSame = + And( + vars.map { + Eq(PathUtils.unfold(it.ref, indexing), PathUtils.unfold(it.ref, indices.last())) + } + ) + itpSolver.add(a, Not(allVarsSame)) } + } - itpSolver.add(b, Not(unfoldedPropExpr(indices.last()))) + if (itpSolver.check().isUnsat) { + itpSolver.pop() + itpSolver.pop() + logger.write(Logger.Level.MAINSTEP, "Safety proven in IMC/BMC step\n") + return SafetyResult.safe(EmptyProof.getInstance(), BoundedStatistics(iteration)) + } + itpSolver.pop() + } - val status = itpSolver.check() + itpSolver.add(b, Not(unfoldedPropExpr(indices.last()))) - if (status.isSat) { - val trace = getTrace(itpSolver.model) - logger.write(Logger.Level.MAINSTEP, "CeX found in IMC/BMC step (length ${trace.length()})\n") - itpSolver.pop() - itpSolver.pop() - return SafetyResult.unsafe(trace, EmptyWitness.getInstance(), BoundedStatistics(iteration)) - } + val status = itpSolver.check() - var img = unfoldedInitExpr - while (itpSolver.check().isUnsat) { - val interpolant = itpSolver.getInterpolant(pattern) - val itpFormula = PathUtils.unfold(PathUtils.foldin(interpolant.eval(a), indices[1]), indices[0]) - itpSolver.pop() - - itpSolver.push() - itpSolver.add(a, itpFormula) - itpSolver.add(a, Not(img)) - val itpStatus = itpSolver.check() - if (itpStatus.isUnsat) { - logger.write(Logger.Level.MAINSTEP, "Safety proven in IMC step\n") - itpSolver.pop() - itpSolver.pop() - return SafetyResult.safe(EmptyWitness.getInstance(), BoundedStatistics(iteration)) - } - itpSolver.pop() - img = Or(img, itpFormula) - - itpSolver.push() - itpSolver.add(a, itpFormula) - itpSolver.add(a, exprs[0]) - itpSolver.add(b, exprs.subList(1, exprs.size)) - itpSolver.add(b, Not(unfoldedPropExpr(indices.last()))) - } + if (status.isSat) { + val trace = getTrace(itpSolver.model) + logger.write(Logger.Level.MAINSTEP, "CeX found in IMC/BMC step (length ${trace.length()})\n") + itpSolver.pop() + itpSolver.pop() + return SafetyResult.unsafe(trace, EmptyProof.getInstance(), BoundedStatistics(iteration)) + } + var img = unfoldedInitExpr + while (itpSolver.check().isUnsat) { + val interpolant = itpSolver.getInterpolant(pattern) + val itpFormula = + PathUtils.unfold(PathUtils.foldin(interpolant.eval(a), indices[1]), indices[0]) + itpSolver.pop() + + itpSolver.push() + itpSolver.add(a, itpFormula) + itpSolver.add(a, Not(img)) + val itpStatus = itpSolver.check() + if (itpStatus.isUnsat) { + logger.write(Logger.Level.MAINSTEP, "Safety proven in IMC step\n") itpSolver.pop() itpSolver.pop() - return null + return SafetyResult.safe(EmptyProof.getInstance(), BoundedStatistics(iteration)) + } + itpSolver.pop() + img = Or(img, itpFormula) + + itpSolver.push() + itpSolver.add(a, itpFormula) + itpSolver.add(a, exprs[0]) + itpSolver.add(b, exprs.subList(1, exprs.size)) + itpSolver.add(b, Not(unfoldedPropExpr(indices.last()))) } - - private fun getTrace(model: Valuation): Trace { - val stateList = LinkedList() - val actionList = LinkedList() - var lastValuation: Valuation? = null - for (i in indices) { - val valuation = PathUtils.extractValuation(model, i, vars) - stateList.add(valToState(valuation)) - if (lastValuation != null) { - actionList.add(biValToAction(lastValuation, valuation)) - } - lastValuation = valuation - } - return Trace.of(stateList, actionList) + itpSolver.pop() + itpSolver.pop() + return null + } + + private fun getTrace(model: Valuation): Trace { + val stateList = LinkedList() + val actionList = LinkedList() + var lastValuation: Valuation? = null + for (i in indices) { + val valuation = PathUtils.extractValuation(model, i, vars) + stateList.add(valToState(valuation)) + if (lastValuation != null) { + actionList.add(biValToAction(lastValuation, valuation)) + } + lastValuation = valuation } - -} \ No newline at end of file + return Trace.of(stateList, actionList) + } +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java index a6cb49bb43..d4601d334e 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Abstractor.java @@ -16,22 +16,17 @@ package hu.bme.mit.theta.analysis.algorithm.cegar; import hu.bme.mit.theta.analysis.Prec; -import hu.bme.mit.theta.analysis.algorithm.Witness; +import hu.bme.mit.theta.analysis.algorithm.Proof; /** - * Common interface for the abstractor component. It can create an initial witness and check a witness with - * a given precision. + * Common interface for the abstractor component. It can create an initial witness and check a + * witness with a given precision. */ -public interface Abstractor

{ +public interface Abstractor

{ - /** - * Create initial witness - */ - W createWitness(); - - /** - * Check witness with given precision - */ - AbstractorResult check(W witness, P prec); + /** Create initial witness */ + Pr createProof(); + /** Check witness with given precision */ + AbstractorResult check(Pr witness, P prec); } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java index 050ae32ce3..a92dbedfc2 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/BasicArgAbstractor.java @@ -15,6 +15,9 @@ */ package hu.bme.mit.theta.analysis.algorithm.cegar; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.State; @@ -30,18 +33,13 @@ import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; import hu.bme.mit.theta.common.logging.NullLogger; - import java.util.Collection; import java.util.Collections; import java.util.function.Function; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -/** - * Basic implementation for the abstractor, relying on an ArgBuilder. - */ -public class BasicArgAbstractor implements ArgAbstractor { +/** Basic implementation for the abstractor, relying on an ArgBuilder. */ +public class BasicArgAbstractor + implements ArgAbstractor { protected final ArgBuilder argBuilder; protected final Function projection; @@ -49,8 +47,12 @@ public class BasicArgAbstractor stopCriterion; protected final Logger logger; - protected BasicArgAbstractor(final ArgBuilder argBuilder, final Function projection, - final Waitlist> waitlist, final StopCriterion stopCriterion, final Logger logger) { + protected BasicArgAbstractor( + final ArgBuilder argBuilder, + final Function projection, + final Waitlist> waitlist, + final StopCriterion stopCriterion, + final Logger logger) { this.argBuilder = checkNotNull(argBuilder); this.projection = checkNotNull(projection); this.waitlist = checkNotNull(waitlist); @@ -64,7 +66,7 @@ public static Builder createWitness() { + public ARG createProof() { return argBuilder.createArg(); } @@ -82,11 +84,16 @@ public AbstractorResult check(final ARG arg, final P prec) { assert arg.isInitialized(); - logger.write(Level.INFO, "| | Starting ARG: %d nodes, %d incomplete, %d unsafe%n", arg.getNodes().count(), - arg.getIncompleteNodes().count(), arg.getUnsafeNodes().count()); + logger.write( + Level.INFO, + "| | Starting ARG: %d nodes, %d incomplete, %d unsafe%n", + arg.getNodes().count(), + arg.getIncompleteNodes().count(), + arg.getUnsafeNodes().count()); logger.write(Level.SUBSTEP, "| | Building ARG..."); - final Partition, ?> reachedSet = Partition.of(n -> projection.apply(n.getState())); + final Partition, ?> reachedSet = + Partition.of(n -> projection.apply(n.getState())); waitlist.clear(); reachedSet.addAll(arg.getNodes()); @@ -109,8 +116,12 @@ public AbstractorResult check(final ARG arg, final P prec) { } logger.write(Level.SUBSTEP, "done%n"); - logger.write(Level.INFO, "| | Finished ARG: %d nodes, %d incomplete, %d unsafe%n", arg.getNodes().count(), - arg.getIncompleteNodes().count(), arg.getUnsafeNodes().count()); + logger.write( + Level.INFO, + "| | Finished ARG: %d nodes, %d incomplete, %d unsafe%n", + arg.getNodes().count(), + arg.getIncompleteNodes().count(), + arg.getUnsafeNodes().count()); waitlist.clear(); // Optimization @@ -175,8 +186,8 @@ public Builder logger(final Logger logger) { } public BasicArgAbstractor build() { - return new BasicArgAbstractor<>(argBuilder, projection, waitlist, stopCriterion, logger); + return new BasicArgAbstractor<>( + argBuilder, projection, waitlist, stopCriterion, logger); } } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java index fa811afc42..30da9a28e5 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java @@ -20,11 +20,11 @@ import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.State; +import hu.bme.mit.theta.analysis.algorithm.Proof; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.SafetyResult; -import hu.bme.mit.theta.analysis.algorithm.Witness; import hu.bme.mit.theta.analysis.runtimemonitor.MonitorCheckpoint; -import hu.bme.mit.theta.analysis.utils.WitnessVisualizer; +import hu.bme.mit.theta.analysis.utils.ProofVisualizer; import hu.bme.mit.theta.common.Utils; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; @@ -42,38 +42,38 @@ * check counterexamples and refine them if needed. It also provides certain * statistics about its execution. */ -public final class CegarChecker implements SafetyChecker { +public final class CegarChecker implements SafetyChecker { - private final Abstractor abstractor; - private final Refiner refiner; + private final Abstractor abstractor; + private final Refiner refiner; private final Logger logger; - private final W witness; - private final WitnessVisualizer witnessVisualizer; + private final Pr proof; + private final ProofVisualizer proofVisualizer; - private CegarChecker(final Abstractor abstractor, final Refiner refiner, final Logger logger, final WitnessVisualizer witnessVisualizer) { + private CegarChecker(final Abstractor abstractor, final Refiner refiner, final Logger logger, final ProofVisualizer proofVisualizer) { this.abstractor = checkNotNull(abstractor); this.refiner = checkNotNull(refiner); this.logger = checkNotNull(logger); - witness = abstractor.createWitness(); - this.witnessVisualizer = checkNotNull(witnessVisualizer); + proof = abstractor.createProof(); + this.proofVisualizer = checkNotNull(proofVisualizer); } - public static CegarChecker create( - final Abstractor abstractor, final Refiner refiner, final WitnessVisualizer witnessVisualizer) { - return create(abstractor, refiner, NullLogger.getInstance(), witnessVisualizer); + public static CegarChecker create( + final Abstractor abstractor, final Refiner refiner, final ProofVisualizer proofVisualizer) { + return create(abstractor, refiner, NullLogger.getInstance(), proofVisualizer); } - public static CegarChecker create( - final Abstractor abstractor, final Refiner refiner, final Logger logger, final WitnessVisualizer witnessVisualizer) { - return new CegarChecker<>(abstractor, refiner, logger, witnessVisualizer); + public static CegarChecker create( + final Abstractor abstractor, final Refiner refiner, final Logger logger, final ProofVisualizer proofVisualizer) { + return new CegarChecker<>(abstractor, refiner, logger, proofVisualizer); } - public W getWitness() { - return witness; + public Pr getProof() { + return proof; } @Override - public SafetyResult check(final P initPrec) { + public SafetyResult check(final P initPrec) { logger.write(Level.INFO, "Configuration: %s%n", this); final Stopwatch stopwatch = Stopwatch.createStarted(); long abstractorTime = 0; @@ -89,12 +89,12 @@ public SafetyResult check(final P initPrec) { logger.write(Level.MAINSTEP, "Iteration %d%n", iteration); logger.write(Level.MAINSTEP, "| Checking abstraction...%n"); final long abstractorStartTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); - abstractorResult = abstractor.check(witness, prec); + abstractorResult = abstractor.check(proof, prec); abstractorTime += stopwatch.elapsed(TimeUnit.MILLISECONDS) - abstractorStartTime; logger.write(Level.MAINSTEP, "| Checking abstraction done, result: %s%n", abstractorResult); if (WebDebuggerLogger.enabled()) { - String argGraph = JSONWriter.getInstance().writeString(witnessVisualizer.visualize(witness)); + String argGraph = JSONWriter.getInstance().writeString(proofVisualizer.visualize(proof)); String precString = prec.toString(); wdl.addIteration(iteration, argGraph, precString); } @@ -105,7 +105,7 @@ public SafetyResult check(final P initPrec) { P lastPrec = prec; logger.write(Level.MAINSTEP, "| Refining abstraction...%n"); final long refinerStartTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); - refinerResult = refiner.refine(witness, prec); + refinerResult = refiner.refine(proof, prec); refinerTime += stopwatch.elapsed(TimeUnit.MILLISECONDS) - refinerStartTime; logger.write(Level.MAINSTEP, "Refining abstraction done, result: %s%n", refinerResult); @@ -124,16 +124,16 @@ public SafetyResult check(final P initPrec) { } while (!abstractorResult.isSafe() && !refinerResult.isUnsafe()); stopwatch.stop(); - SafetyResult cegarResult = null; + SafetyResult cegarResult = null; final CegarStatistics stats = new CegarStatistics(stopwatch.elapsed(TimeUnit.MILLISECONDS), abstractorTime, refinerTime, iteration); assert abstractorResult.isSafe() || refinerResult.isUnsafe(); if (abstractorResult.isSafe()) { - cegarResult = SafetyResult.safe(witness, stats); + cegarResult = SafetyResult.safe(proof, stats); } else if (refinerResult.isUnsafe()) { - cegarResult = SafetyResult.unsafe(refinerResult.asUnsafe().getCex(), witness, stats); + cegarResult = SafetyResult.unsafe(refinerResult.asUnsafe().getCex(), proof, stats); } assert cegarResult != null; diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java index 6eca5d7c21..abd645f3cf 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java @@ -19,16 +19,16 @@ import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.State; -import hu.bme.mit.theta.analysis.algorithm.Witness; +import hu.bme.mit.theta.analysis.algorithm.Proof; /** * Common interface for refiners. It takes a witness and a precision, checks if the counterexample in * the witness is feasible and if not, it refines the precision */ -public interface Refiner { +public interface Refiner { /** * Checks if the counterexample in the witness is feasible. If not, refines the precision */ - RefinerResult refine(W witness, P prec); + RefinerResult refine(Pr witness, P prec); } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/chc/HornChecker.kt b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/chc/HornChecker.kt index 0c083b7cd0..a52da53d51 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/chc/HornChecker.kt +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/chc/HornChecker.kt @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.analysis.algorithm.chc import hu.bme.mit.theta.analysis.Cex +import hu.bme.mit.theta.analysis.algorithm.Proof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult -import hu.bme.mit.theta.analysis.algorithm.Witness import hu.bme.mit.theta.analysis.unit.UnitPrec import hu.bme.mit.theta.common.logging.Logger import hu.bme.mit.theta.core.Relation @@ -30,58 +29,62 @@ import hu.bme.mit.theta.solver.ProofNode import hu.bme.mit.theta.solver.SolverFactory import hu.bme.mit.theta.solver.SolverStatus -data class Invariant(val lookup: Map>) : Witness +data class Invariant(val lookup: Map>) : Proof data class CexTree(val proofNode: ProofNode) : Cex { - override fun length(): Int = proofNode.depth() + override fun length(): Int = proofNode.depth() } -/** - * A checker for CHC-based verification. - */ +/** A checker for CHC-based verification. */ class HornChecker( - private val relations: List, - private val hornSolverFactory: SolverFactory, - private val logger: Logger, + private val relations: List, + private val hornSolverFactory: SolverFactory, + private val logger: Logger, ) : SafetyChecker { - override fun check(prec: UnitPrec?): SafetyResult { - val solver = hornSolverFactory.createHornSolver() - logger.write(Logger.Level.MAINSTEP, "Starting encoding\n") - solver.add(relations) - logger.write(Logger.Level.DETAIL, "Relations:\n\t${ + override fun check(prec: UnitPrec?): SafetyResult { + val solver = hornSolverFactory.createHornSolver() + logger.write(Logger.Level.MAINSTEP, "Starting encoding\n") + solver.add(relations) + logger.write( + Logger.Level.DETAIL, + "Relations:\n\t${ relations.joinToString("\n\t") { it.constDecl.toString() } - }\n") - logger.write(Logger.Level.DETAIL, "Rules:\n\t${ + }\n", + ) + logger.write( + Logger.Level.DETAIL, + "Rules:\n\t${ solver.assertions.joinToString("\n\t") { it.toString().replace(Regex("[\r\n\t ]+"), " ") } - }\n") - logger.write(Logger.Level.MAINSTEP, "Added constraints to solver\n") - solver.check() - logger.write(Logger.Level.MAINSTEP, "Check() finished (result: ${solver.status})\n") - return when (solver.status) { - SolverStatus.SAT -> { - logger.write(Logger.Level.MAINSTEP, "Proof (model) found\n") - val model = solver.model.toMap() - SafetyResult.safe( - Invariant(relations.associateWith { model[it.constDecl] as? Expr ?: True() })) - } + }\n", + ) + logger.write(Logger.Level.MAINSTEP, "Added constraints to solver\n") + solver.check() + logger.write(Logger.Level.MAINSTEP, "Check() finished (result: ${solver.status})\n") + return when (solver.status) { + SolverStatus.SAT -> { + logger.write(Logger.Level.MAINSTEP, "Proof (model) found\n") + val model = solver.model.toMap() + SafetyResult.safe( + Invariant(relations.associateWith { model[it.constDecl] as? Expr ?: True() }) + ) + } - SolverStatus.UNSAT -> { - logger.write(Logger.Level.MAINSTEP, "Counterexample found\n") - val proof = solver.proof - SafetyResult.unsafe(CexTree(proof), Invariant(emptyMap())) - } + SolverStatus.UNSAT -> { + logger.write(Logger.Level.MAINSTEP, "Counterexample found\n") + val proof = solver.proof + SafetyResult.unsafe(CexTree(proof), Invariant(emptyMap())) + } - else -> { - logger.write(Logger.Level.MAINSTEP, "No solution found.\n") - SafetyResult.unknown() - } - } + else -> { + logger.write(Logger.Level.MAINSTEP, "No solution found.\n") + SafetyResult.unknown() + } } - -} \ No newline at end of file + } +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mcm/analysis/FiniteStateChecker.kt b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mcm/analysis/FiniteStateChecker.kt index 05c02303c3..b316300d9c 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mcm/analysis/FiniteStateChecker.kt +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mcm/analysis/FiniteStateChecker.kt @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.analysis.algorithm.mcm.analysis import hu.bme.mit.theta.analysis.EmptyCex import hu.bme.mit.theta.analysis.InitFunc import hu.bme.mit.theta.analysis.LTS import hu.bme.mit.theta.analysis.TransFunc -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.mcm.interpreter.MemoryEventProvider @@ -35,52 +34,52 @@ import hu.bme.mit.theta.graphsolver.patterns.constraints.GraphConstraint import hu.bme.mit.theta.graphsolver.solvers.GraphSolver import java.util.* -/** - * WiP checker for finite-state systems - */ +/** WiP checker for finite-state systems */ class FiniteStateChecker( - private val mcm: Collection, - private val initFunc: InitFunc, - private val actionFunc: LTS, - private val transFunc: TransFunc, - private val memoryEventProvider: MemoryEventProvider, - private val graphPatternCompiler: GraphPatternCompiler, - private val graphPatternSolver: GraphSolver -) : SafetyChecker { + private val mcm: Collection, + private val initFunc: InitFunc, + private val actionFunc: LTS, + private val transFunc: TransFunc, + private val memoryEventProvider: MemoryEventProvider, + private val graphPatternCompiler: GraphPatternCompiler, + private val graphPatternSolver: GraphSolver, +) : SafetyChecker { - override fun check(prec: ExplPrec): SafetyResult { - val eventIds = LinkedList() - val rels = LinkedList>() - val lastIds = LinkedHashMap() - val initId = nextId(eventIds) - val initStates = LinkedList(initFunc.getInitStates(prec)) - initStates.forEach { lastIds[it] = initId } - while (initStates.isNotEmpty()) { - val state = initStates.pop() - val lastId = checkNotNull(lastIds[state]) - val actions = actionFunc.getEnabledActionsFor(state) - - val nextStates = actions.map { a -> - val memEvent = memoryEventProvider[a, prec] - transFunc.getSuccStates(state, a, prec).onEach { s -> - memEvent?.also { - val id = nextId(eventIds) - rels.add(Pair(memEvent.type().label, Tuple1.of(id))) - rels.add(Pair("po", Tuple2.of(lastId, id))) - lastIds[s] = id - } - } - }.flatten() - initStates.addAll(nextStates) - } -// PartialSolver(mcm, CandidateExecutionGraph(eventIds, rels)) - return SafetyResult.unsafe(EmptyCex.getInstance(), EmptyWitness.getInstance()) + override fun check(prec: ExplPrec): SafetyResult { + val eventIds = LinkedList() + val rels = LinkedList>() + val lastIds = LinkedHashMap() + val initId = nextId(eventIds) + val initStates = LinkedList(initFunc.getInitStates(prec)) + initStates.forEach { lastIds[it] = initId } + while (initStates.isNotEmpty()) { + val state = initStates.pop() + val lastId = checkNotNull(lastIds[state]) + val actions = actionFunc.getEnabledActionsFor(state) + val nextStates = + actions + .map { a -> + val memEvent = memoryEventProvider[a, prec] + transFunc.getSuccStates(state, a, prec).onEach { s -> + memEvent?.also { + val id = nextId(eventIds) + rels.add(Pair(memEvent.type().label, Tuple1.of(id))) + rels.add(Pair("po", Tuple2.of(lastId, id))) + lastIds[s] = id + } + } + } + .flatten() + initStates.addAll(nextStates) } + // PartialSolver(mcm, CandidateExecutionGraph(eventIds, rels)) + return SafetyResult.unsafe(EmptyCex.getInstance(), EmptyProof.getInstance()) + } - private fun nextId(list: MutableList): Int { - val ret = list.size - list.add(list.size) - return ret - } -} \ No newline at end of file + private fun nextId(list: MutableList): Int { + val ret = list.size + list.add(list.size) + return ret + } +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddChecker.java index df1feb4743..cd81d5a697 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddChecker.java @@ -15,28 +15,28 @@ */ package hu.bme.mit.theta.analysis.algorithm.mdd; -import hu.bme.mit.delta.collections.impl.RecursiveIntObjMapViews; -import hu.bme.mit.delta.java.mdd.*; +import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not; + +import hu.bme.mit.delta.java.mdd.JavaMddFactory; +import hu.bme.mit.delta.java.mdd.MddGraph; +import hu.bme.mit.delta.java.mdd.MddHandle; +import hu.bme.mit.delta.java.mdd.MddVariableOrder; import hu.bme.mit.delta.mdd.MddInterpreter; import hu.bme.mit.delta.mdd.MddVariableDescriptor; -import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; +import hu.bme.mit.theta.analysis.algorithm.SafetyResult; +import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.AbstractNextStateDescriptor; +import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeInitializer; +import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeNextStateDescriptor; +import hu.bme.mit.theta.analysis.algorithm.mdd.expressionnode.ExprLatticeDefinition; +import hu.bme.mit.theta.analysis.algorithm.mdd.expressionnode.MddExpressionTemplate; import hu.bme.mit.theta.analysis.algorithm.mdd.fixedpoint.BfsProvider; import hu.bme.mit.theta.analysis.algorithm.mdd.fixedpoint.GeneralizedSaturationProvider; -import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.AbstractNextStateDescriptor; import hu.bme.mit.theta.analysis.algorithm.mdd.fixedpoint.SimpleSaturationProvider; import hu.bme.mit.theta.analysis.algorithm.mdd.fixedpoint.StateSpaceEnumerationProvider; -import hu.bme.mit.theta.common.logging.Logger.Level; -import hu.bme.mit.theta.solver.SolverPool; -import hu.bme.mit.theta.analysis.algorithm.mdd.expressionnode.ExprLatticeDefinition; -import hu.bme.mit.theta.analysis.algorithm.mdd.expressionnode.MddExpressionTemplate; -import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeInitializer; -import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeNextStateDescriptor; import hu.bme.mit.theta.analysis.expr.ExprAction; -import hu.bme.mit.theta.analysis.utils.MddNodeVisualizer; import hu.bme.mit.theta.common.logging.Logger; -import hu.bme.mit.theta.common.visualization.Graph; -import hu.bme.mit.theta.common.visualization.writer.GraphvizWriter; +import hu.bme.mit.theta.common.logging.Logger.Level; import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; @@ -45,15 +45,11 @@ import hu.bme.mit.theta.core.utils.PathUtils; import hu.bme.mit.theta.core.utils.indexings.VarIndexing; import hu.bme.mit.theta.core.utils.indexings.VarIndexingFactory; -import hu.bme.mit.theta.solver.SolverFactory; - -import java.io.FileNotFoundException; +import hu.bme.mit.theta.solver.SolverPool; import java.util.List; import java.util.Set; -import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not; - -public class MddChecker implements SafetyChecker { +public class MddChecker implements SafetyChecker { private final Expr initRel; private final VarIndexing initIndexing; @@ -64,16 +60,19 @@ public class MddChecker implements SafetyChecker initRel, - VarIndexing initIndexing, - A transRel, - Expr safetyProperty, - SolverPool solverPool, - Logger logger, - IterationStrategy iterationStrategy) { + private MddChecker( + Expr initRel, + VarIndexing initIndexing, + A transRel, + Expr safetyProperty, + SolverPool solverPool, + Logger logger, + IterationStrategy iterationStrategy) { this.initRel = initRel; this.initIndexing = initIndexing; this.transRel = transRel; @@ -83,40 +82,63 @@ private MddChecker(Expr initRel, this.iterationStrategy = iterationStrategy; } - public static MddChecker create(Expr initRel, - VarIndexing initIndexing, - A transRel, - Expr safetyProperty, - SolverPool solverPool, - Logger logger) { - return new MddChecker(initRel, initIndexing, transRel, safetyProperty, solverPool, logger, IterationStrategy.GSAT); + public static MddChecker create( + Expr initRel, + VarIndexing initIndexing, + A transRel, + Expr safetyProperty, + SolverPool solverPool, + Logger logger) { + return new MddChecker( + initRel, + initIndexing, + transRel, + safetyProperty, + solverPool, + logger, + IterationStrategy.GSAT); } - public static MddChecker create(Expr initRel, - VarIndexing initIndexing, - A transRel, - Expr safetyProperty, - SolverPool solverPool, - Logger logger, - IterationStrategy iterationStrategy) { - return new MddChecker(initRel, initIndexing, transRel, safetyProperty, solverPool, logger, iterationStrategy); + public static MddChecker create( + Expr initRel, + VarIndexing initIndexing, + A transRel, + Expr safetyProperty, + SolverPool solverPool, + Logger logger, + IterationStrategy iterationStrategy) { + return new MddChecker( + initRel, + initIndexing, + transRel, + safetyProperty, + solverPool, + logger, + iterationStrategy); } @Override - public SafetyResult check(Void input) { + public SafetyResult check(Void input) { - final MddGraph mddGraph = JavaMddFactory.getDefault().createMddGraph(ExprLatticeDefinition.forExpr()); + final MddGraph mddGraph = + JavaMddFactory.getDefault().createMddGraph(ExprLatticeDefinition.forExpr()); - final MddVariableOrder stateOrder = JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); - final MddVariableOrder transOrder = JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); + final MddVariableOrder stateOrder = + JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); + final MddVariableOrder transOrder = + JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); - final Set> vars = ExprUtils.getVars(List.of(initRel, transRel.toExpr(), safetyProperty)); + final Set> vars = + ExprUtils.getVars(List.of(initRel, transRel.toExpr(), safetyProperty)); for (var v : vars) { final var domainSize = v.getType() instanceof BoolType ? 2 : 0; - stateOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(initIndexing.get(v)), domainSize)); + stateOrder.createOnTop( + MddVariableDescriptor.create(v.getConstDecl(initIndexing.get(v)), domainSize)); - transOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(transRel.nextIndexing().get(v)), domainSize)); + transOrder.createOnTop( + MddVariableDescriptor.create( + v.getConstDecl(transRel.nextIndexing().get(v)), domainSize)); transOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(0), domainSize)); } @@ -124,13 +146,20 @@ public SafetyResult check(Void input) { final var transSig = transOrder.getDefaultSetSignature(); final Expr initExpr = PathUtils.unfold(initRel, initIndexing); - final MddHandle initNode = stateSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(initExpr, o -> (Decl) o, solverPool)); + final MddHandle initNode = + stateSig.getTopVariableHandle() + .checkInNode(MddExpressionTemplate.of(initExpr, o -> (Decl) o, solverPool)); logger.write(Level.INFO, "Created initial node"); - final Expr transExpr = PathUtils.unfold(transRel.toExpr(), VarIndexingFactory.indexing(0)); - final MddHandle transitionNode = transSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(transExpr, o -> (Decl) o, solverPool)); - final AbstractNextStateDescriptor nextStates = MddNodeNextStateDescriptor.of(transitionNode); + final Expr transExpr = + PathUtils.unfold(transRel.toExpr(), VarIndexingFactory.indexing(0)); + final MddHandle transitionNode = + transSig.getTopVariableHandle() + .checkInNode( + MddExpressionTemplate.of(transExpr, o -> (Decl) o, solverPool)); + final AbstractNextStateDescriptor nextStates = + MddNodeNextStateDescriptor.of(transitionNode); logger.write(Level.INFO, "Created next-state node, starting fixed point calculation"); @@ -147,12 +176,20 @@ public SafetyResult check(Void input) { } default -> throw new IllegalStateException("Unexpected value: " + iterationStrategy); } - final MddHandle stateSpace = stateSpaceProvider.compute(MddNodeInitializer.of(initNode), nextStates, stateSig.getTopVariableHandle()); + final MddHandle stateSpace = + stateSpaceProvider.compute( + MddNodeInitializer.of(initNode), + nextStates, + stateSig.getTopVariableHandle()); logger.write(Level.INFO, "Enumerated state-space"); final Expr negatedPropExpr = PathUtils.unfold(Not(safetyProperty), initIndexing); - final MddHandle propNode = stateSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(negatedPropExpr, o -> (Decl) o, solverPool)); + final MddHandle propNode = + stateSig.getTopVariableHandle() + .checkInNode( + MddExpressionTemplate.of( + negatedPropExpr, o -> (Decl) o, solverPool)); final MddHandle propViolating = (MddHandle) stateSpace.intersection(propNode); @@ -164,13 +201,21 @@ public SafetyResult check(Void input) { final Long stateSpaceSize = MddInterpreter.calculateNonzeroCount(stateSpace); logger.write(Level.DETAIL, "State space size: " + stateSpaceSize); - final MddAnalysisStatistics statistics = new MddAnalysisStatistics(violatingSize, stateSpaceSize, stateSpaceProvider.getHitCount(), stateSpaceProvider.getQueryCount(), stateSpaceProvider.getCacheSize()); + final MddAnalysisStatistics statistics = + new MddAnalysisStatistics( + violatingSize, + stateSpaceSize, + stateSpaceProvider.getHitCount(), + stateSpaceProvider.getQueryCount(), + stateSpaceProvider.getCacheSize()); - final SafetyResult result; + final SafetyResult result; if (violatingSize != 0) { - result = SafetyResult.unsafe(MddCex.of(propViolating), MddWitness.of(stateSpace), statistics); + result = + SafetyResult.unsafe( + MddCex.of(propViolating), MddProof.of(stateSpace), statistics); } else { - result = SafetyResult.safe(MddWitness.of(stateSpace), statistics); + result = SafetyResult.safe(MddProof.of(stateSpace), statistics); } logger.write(Level.RESULT, "%s%n", result); return result; diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddWitness.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddProof.java similarity index 81% rename from subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddWitness.java rename to subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddProof.java index 300dc6579f..805a138399 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddWitness.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddProof.java @@ -17,18 +17,18 @@ import hu.bme.mit.delta.java.mdd.MddHandle; import hu.bme.mit.delta.mdd.MddInterpreter; -import hu.bme.mit.theta.analysis.algorithm.Witness; +import hu.bme.mit.theta.analysis.algorithm.Proof; -public class MddWitness implements Witness { +public class MddProof implements Proof { private final MddHandle stateSpace; - private MddWitness(MddHandle stateSpace) { + private MddProof(MddHandle stateSpace) { this.stateSpace = stateSpace; } - public static MddWitness of(MddHandle stateSpace) { - return new MddWitness(stateSpace); + public static MddProof of(MddHandle stateSpace) { + return new MddProof(stateSpace); } public Long size() { diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java index c4c82eeb74..89efd988a5 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ArgVisualizer.java @@ -18,25 +18,23 @@ import static hu.bme.mit.theta.common.visualization.Alignment.LEFT; import static hu.bme.mit.theta.common.visualization.Shape.RECTANGLE; -import java.awt.Color; - -import hu.bme.mit.theta.common.container.Containers; - -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgEdge; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode; +import hu.bme.mit.theta.common.container.Containers; import hu.bme.mit.theta.common.visualization.EdgeAttributes; import hu.bme.mit.theta.common.visualization.Graph; import hu.bme.mit.theta.common.visualization.LineStyle; import hu.bme.mit.theta.common.visualization.NodeAttributes; +import java.awt.*; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; -public final class ArgVisualizer implements WitnessVisualizer> { +public final class ArgVisualizer + implements ProofVisualizer> { private static final LineStyle COVER_EDGE_STYLE = LineStyle.DASHED; private static final LineStyle SUCC_EDGE_STYLE = LineStyle.NORMAL; @@ -53,8 +51,8 @@ public final class ArgVisualizer implements W private static class LazyHolderDefault { - static final ArgVisualizer INSTANCE = new ArgVisualizer<>(Object::toString, - Object::toString); + static final ArgVisualizer INSTANCE = + new ArgVisualizer<>(Object::toString, Object::toString); } private static class LazyHolderStructureOnly { @@ -62,8 +60,8 @@ private static class LazyHolderStructureOnly { static final ArgVisualizer INSTANCE = new ArgVisualizer<>(s -> "", a -> ""); } - public ArgVisualizer(final Function stateToString, - final Function actionToString) { + public ArgVisualizer( + final Function stateToString, final Function actionToString) { this.stateToString = stateToString; this.actionToString = actionToString; } @@ -87,24 +85,37 @@ public Graph visualize(final ARG arg) { final Set> traversed = Containers.createSet(); - for (final ArgNode initNode : arg.getInitNodes() - .collect(Collectors.toSet())) { + for (final ArgNode initNode : + arg.getInitNodes().collect(Collectors.toSet())) { traverse(graph, initNode, traversed); - final NodeAttributes nAttributes = NodeAttributes.builder().label("") - .fillColor(FILL_COLOR) - .lineColor(FILL_COLOR).lineStyle(SUCC_EDGE_STYLE).peripheries(1).build(); + final NodeAttributes nAttributes = + NodeAttributes.builder() + .label("") + .fillColor(FILL_COLOR) + .lineColor(FILL_COLOR) + .lineStyle(SUCC_EDGE_STYLE) + .peripheries(1) + .build(); graph.addNode(PHANTOM_INIT_ID + initNode.getId(), nAttributes); - final EdgeAttributes eAttributes = EdgeAttributes.builder().label("").color(LINE_COLOR) - .lineStyle(SUCC_EDGE_STYLE).build(); - graph.addEdge(PHANTOM_INIT_ID + initNode.getId(), NODE_ID_PREFIX + initNode.getId(), + final EdgeAttributes eAttributes = + EdgeAttributes.builder() + .label("") + .color(LINE_COLOR) + .lineStyle(SUCC_EDGE_STYLE) + .build(); + graph.addEdge( + PHANTOM_INIT_ID + initNode.getId(), + NODE_ID_PREFIX + initNode.getId(), eAttributes); } return graph; } - private void traverse(final Graph graph, final ArgNode node, - final Set> traversed) { + private void traverse( + final Graph graph, + final ArgNode node, + final Set> traversed) { if (traversed.contains(node)) { return; } else { @@ -114,21 +125,33 @@ private void traverse(final Graph graph, final ArgNode final LineStyle lineStyle = SUCC_EDGE_STYLE; final int peripheries = node.isTarget() ? 2 : 1; - final NodeAttributes nAttributes = NodeAttributes.builder() - .label(stateToString.apply(node.getState())) - .alignment(LEFT).shape(RECTANGLE).font(FONT).fillColor(FILL_COLOR).lineColor(LINE_COLOR) - .lineStyle(lineStyle).peripheries(peripheries).build(); + final NodeAttributes nAttributes = + NodeAttributes.builder() + .label(stateToString.apply(node.getState())) + .alignment(LEFT) + .shape(RECTANGLE) + .font(FONT) + .fillColor(FILL_COLOR) + .lineColor(LINE_COLOR) + .lineStyle(lineStyle) + .peripheries(peripheries) + .build(); graph.addNode(nodeId, nAttributes); - for (final ArgEdge edge : node.getOutEdges() - .collect(Collectors.toSet())) { + for (final ArgEdge edge : + node.getOutEdges().collect(Collectors.toSet())) { traverse(graph, edge.getTarget(), traversed); final String sourceId = NODE_ID_PREFIX + edge.getSource().getId(); final String targetId = NODE_ID_PREFIX + edge.getTarget().getId(); - final EdgeAttributes eAttributes = EdgeAttributes.builder() - .label(actionToString.apply(edge.getAction())) - .alignment(LEFT).font(FONT).color(LINE_COLOR).lineStyle(SUCC_EDGE_STYLE).build(); + final EdgeAttributes eAttributes = + EdgeAttributes.builder() + .label(actionToString.apply(edge.getAction())) + .alignment(LEFT) + .font(FONT) + .color(LINE_COLOR) + .lineStyle(SUCC_EDGE_STYLE) + .build(); graph.addEdge(sourceId, targetId, eAttributes); } @@ -136,10 +159,14 @@ private void traverse(final Graph graph, final ArgNode traverse(graph, node.getCoveringNode().get(), traversed); final String sourceId = NODE_ID_PREFIX + node.getId(); final String targetId = NODE_ID_PREFIX + node.getCoveringNode().get().getId(); - final EdgeAttributes eAttributes = EdgeAttributes.builder().label("").color(LINE_COLOR) - .lineStyle(COVER_EDGE_STYLE).weight(0).build(); + final EdgeAttributes eAttributes = + EdgeAttributes.builder() + .label("") + .color(LINE_COLOR) + .lineStyle(COVER_EDGE_STYLE) + .weight(0) + .build(); graph.addEdge(sourceId, targetId, eAttributes); } } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ProofVisualizer.java similarity index 83% rename from subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java rename to subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ProofVisualizer.java index bd1a9d8234..954604871d 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/WitnessVisualizer.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/utils/ProofVisualizer.java @@ -13,14 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.analysis.utils; -import hu.bme.mit.theta.analysis.algorithm.Witness; +import hu.bme.mit.theta.analysis.algorithm.Proof; import hu.bme.mit.theta.common.visualization.Graph; -public interface WitnessVisualizer { - - Graph visualize(W witness); +public interface ProofVisualizer { + Graph visualize(Pr proof); } diff --git a/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddCheckerTest.java b/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddCheckerTest.java index 070daeb91f..0f9f524354 100644 --- a/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddCheckerTest.java +++ b/subprojects/common/analysis/src/test/java/hu/bme/mit/theta/analysis/algorithm/mdd/MddCheckerTest.java @@ -15,6 +15,14 @@ */ package hu.bme.mit.theta.analysis.algorithm.mdd; +import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.*; +import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.common.logging.ConsoleLogger; @@ -29,31 +37,19 @@ import hu.bme.mit.theta.core.utils.indexings.VarIndexingFactory; import hu.bme.mit.theta.solver.SolverPool; import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory; +import java.util.Arrays; +import java.util.Collection; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; - -import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.*; -import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - @RunWith(value = Parameterized.class) - public class MddCheckerTest { private static final VarDecl X = Decls.Var("x", IntType.getInstance()); private static final VarDecl Y = Decls.Var("y", IntType.getInstance()); private static final VarDecl Z = Decls.Var("z", IntType.getInstance()); - @Parameterized.Parameter(value = 0) public Expr initExpr; @@ -71,57 +67,86 @@ public class MddCheckerTest { @Parameterized.Parameters(name = "{index}: {0}, {1}, {2}, {3}, {4}") public static Collection data() { - return Arrays.asList(new Object[][]{ - - {Eq(X.getRef(), Int(0)), // x = 0 + return Arrays.asList( + new Object[][] { + { + Eq(X.getRef(), Int(0)), // x = 0 Eq(Prime(X.getRef()), X.getRef()), // x'=x Not(Eq(X.getRef(), Int(5))), // not x = 5 true, - 1L}, - - {Eq(X.getRef(), Int(0)), + 1L + }, + { + Eq(X.getRef(), Int(0)), Eq(Prime(X.getRef()), X.getRef()), Not(Eq(X.getRef(), Int(0))), false, - 1L}, - - {Eq(X.getRef(), Int(0)), // x = 0 - And(Eq(Prime(X.getRef()), Add(X.getRef(), Int(1))), Leq(Prime(X.getRef()), Int(10))), // x' = x + 1 & x' <= 10 + 1L + }, + { + Eq(X.getRef(), Int(0)), // x = 0 + And( + Eq(Prime(X.getRef()), Add(X.getRef(), Int(1))), + Leq(Prime(X.getRef()), Int(10))), // x' = x + 1 & x' <= 10 Not(Eq(X.getRef(), Int(5))), false, - 11L}, - - {Eq(X.getRef(), Int(0)), - And(Eq(Prime(X.getRef()), Add(X.getRef(), Int(1))), Leq(Prime(X.getRef()), Int(5))), + 11L + }, + { + Eq(X.getRef(), Int(0)), + And( + Eq(Prime(X.getRef()), Add(X.getRef(), Int(1))), + Leq(Prime(X.getRef()), Int(5))), Not(Eq(X.getRef(), Int(5))), false, - 6L}, - - {Eq(X.getRef(), Int(0)), - And(Eq(Prime(X.getRef()), Add(X.getRef(), Int(1))), Leq(Prime(X.getRef()), Int(4))), + 6L + }, + { + Eq(X.getRef(), Int(0)), + And( + Eq(Prime(X.getRef()), Add(X.getRef(), Int(1))), + Leq(Prime(X.getRef()), Int(4))), Not(Eq(X.getRef(), Int(5))), true, - 5L}, - - {And(Eq(X.getRef(), Int(0)), Eq(Y.getRef(), Int(0)), Eq(Z.getRef(), Int(0))), - And(And(Eq(Prime(X.getRef()), Add(Y.getRef(), Int(1))), Eq(Prime(Y.getRef()), Add(Z.getRef(), Int(1))), Eq(Prime(Z.getRef()), Add(Z.getRef(), Int(1)))), IntExprs.Lt(Prime(Z.getRef()), Int(10))), + 5L + }, + { + And(Eq(X.getRef(), Int(0)), Eq(Y.getRef(), Int(0)), Eq(Z.getRef(), Int(0))), + And( + And( + Eq(Prime(X.getRef()), Add(Y.getRef(), Int(1))), + Eq(Prime(Y.getRef()), Add(Z.getRef(), Int(1))), + Eq(Prime(Z.getRef()), Add(Z.getRef(), Int(1)))), + IntExprs.Lt(Prime(Z.getRef()), Int(10))), Not(Eq(X.getRef(), Int(5))), false, - 10L}, - - {And(Eq(X.getRef(), Int(0)), Eq(Y.getRef(), Int(0)), Eq(Z.getRef(), Int(0))), - And(And(Eq(Prime(X.getRef()), Add(Y.getRef(), Int(1))), Eq(Prime(Y.getRef()), Add(Z.getRef(), Int(1))), Eq(Prime(Z.getRef()), Add(Z.getRef(), Int(1)))), IntExprs.Lt(Prime(Z.getRef()), Int(6))), + 10L + }, + { + And(Eq(X.getRef(), Int(0)), Eq(Y.getRef(), Int(0)), Eq(Z.getRef(), Int(0))), + And( + And( + Eq(Prime(X.getRef()), Add(Y.getRef(), Int(1))), + Eq(Prime(Y.getRef()), Add(Z.getRef(), Int(1))), + Eq(Prime(Z.getRef()), Add(Z.getRef(), Int(1)))), + IntExprs.Lt(Prime(Z.getRef()), Int(6))), Not(Eq(X.getRef(), Int(5))), false, - 6L}, - - {And(Eq(X.getRef(), Int(0)), Eq(Y.getRef(), Int(0)), Eq(Z.getRef(), Int(0))), - And(And(Eq(Prime(X.getRef()), Add(Y.getRef(), Int(1))), Eq(Prime(Y.getRef()), Add(Z.getRef(), Int(1))), Eq(Prime(Z.getRef()), Add(Z.getRef(), Int(1)))), IntExprs.Lt(Prime(Z.getRef()), Int(5))), + 6L + }, + { + And(Eq(X.getRef(), Int(0)), Eq(Y.getRef(), Int(0)), Eq(Z.getRef(), Int(0))), + And( + And( + Eq(Prime(X.getRef()), Add(Y.getRef(), Int(1))), + Eq(Prime(Y.getRef()), Add(Z.getRef(), Int(1))), + Eq(Prime(Z.getRef()), Add(Z.getRef(), Int(1)))), + IntExprs.Lt(Prime(Z.getRef()), Int(5))), Not(Eq(X.getRef(), Int(5))), true, - 5L}, - - }); + 5L + }, + }); } @Test @@ -139,23 +164,32 @@ public void testGsat() throws Exception { testWithIterationStrategy(MddChecker.IterationStrategy.GSAT); } - public void testWithIterationStrategy(MddChecker.IterationStrategy iterationStrategy) throws Exception { + public void testWithIterationStrategy(MddChecker.IterationStrategy iterationStrategy) + throws Exception { final Logger logger = new ConsoleLogger(Logger.Level.SUBSTEP); - final SafetyResult status; + final SafetyResult status; try (var solverPool = new SolverPool(Z3LegacySolverFactory.getInstance())) { - final MddChecker checker = MddChecker.create(initExpr, VarIndexingFactory.indexing(0), new ExprAction() { - @Override - public Expr toExpr() { - return tranExpr; - } - - @Override - public VarIndexing nextIndexing() { - return VarIndexingFactory.indexing(1); - } - }, propExpr, solverPool, logger, iterationStrategy); + final MddChecker checker = + MddChecker.create( + initExpr, + VarIndexingFactory.indexing(0), + new ExprAction() { + @Override + public Expr toExpr() { + return tranExpr; + } + + @Override + public VarIndexing nextIndexing() { + return VarIndexingFactory.indexing(1); + } + }, + propExpr, + solverPool, + logger, + iterationStrategy); status = checker.check(null); } @@ -164,9 +198,6 @@ public VarIndexing nextIndexing() { } else { assertTrue(status.isUnsafe()); } - assertEquals(stateSpaceSize, status.getWitness().size()); - - + assertEquals(stateSpaceSize, status.getProof().size()); } - } diff --git a/subprojects/common/grammar/src/main/java/hu/bme/mit/theta/grammar/gson/SafetyResultAdapter.kt b/subprojects/common/grammar/src/main/java/hu/bme/mit/theta/grammar/gson/SafetyResultAdapter.kt index 6829d577c0..0cd6eb5b2f 100644 --- a/subprojects/common/grammar/src/main/java/hu/bme/mit/theta/grammar/gson/SafetyResultAdapter.kt +++ b/subprojects/common/grammar/src/main/java/hu/bme/mit/theta/grammar/gson/SafetyResultAdapter.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.grammar.gson import com.google.gson.Gson @@ -24,72 +23,75 @@ import com.google.gson.stream.JsonWriter import hu.bme.mit.theta.analysis.Action import hu.bme.mit.theta.analysis.State import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.arg.ARG import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.Statistics +import hu.bme.mit.theta.analysis.algorithm.arg.ARG import java.lang.reflect.Type import java.util.* class SafetyResultAdapter( - val gsonSupplier: () -> Gson, - private val argTypeSupplier: () -> Type, - private val traceTypeSupplier: () -> Type, + val gsonSupplier: () -> Gson, + private val argTypeSupplier: () -> Type, + private val traceTypeSupplier: () -> Type, ) : TypeAdapter, Trace>>() { - private lateinit var gson: Gson - private lateinit var argType: Type - private lateinit var traceType: Type + private lateinit var gson: Gson + private lateinit var argType: Type + private lateinit var traceType: Type - override fun write(writer: JsonWriter, - value: SafetyResult, Trace>) { - initGson() - writer.beginObject() - writer.name("arg") - gson.toJson(gson.toJsonTree(value.witness), writer) - writer.name("stats") -// gson.toJson(gson.toJsonTree(value.stats), writer) - gson.toJson(gson.toJsonTree(Optional.empty()), writer) - if (value.isSafe) { - writer.name("safe").value(true) - } else { - val unsafe = value.asUnsafe() - writer.name("safe").value(false) - writer.name("trace") - gson.toJson(gson.toJsonTree(unsafe.cex), writer) - } - writer.endObject() + override fun write( + writer: JsonWriter, + value: SafetyResult, Trace>, + ) { + initGson() + writer.beginObject() + writer.name("arg") + gson.toJson(gson.toJsonTree(value.proof), writer) + writer.name("stats") + // gson.toJson(gson.toJsonTree(value.stats), writer) + gson.toJson(gson.toJsonTree(Optional.empty()), writer) + if (value.isSafe) { + writer.name("safe").value(true) + } else { + val unsafe = value.asUnsafe() + writer.name("safe").value(false) + writer.name("trace") + gson.toJson(gson.toJsonTree(unsafe.cex), writer) } + writer.endObject() + } - override fun read(reader: JsonReader): SafetyResult, Trace> { - initGson() - initTypes() - lateinit var arg: ARG - lateinit var stats: Optional - var safe: Boolean? = null - lateinit var trace: Trace - reader.beginObject() - while (reader.peek() != JsonToken.END_OBJECT) { - when (reader.nextName()) { - "arg" -> arg = gson.fromJson(reader, argType) - "stats" -> stats = gson.fromJson(reader, Optional::class.java) - "safe" -> safe = reader.nextBoolean() - "trace" -> trace = gson.fromJson(reader, traceType) - } - } - reader.endObject() - return if (stats.isEmpty) - if (safe == true) SafetyResult.safe(arg) else SafetyResult.unsafe(trace, arg) - else - if (safe == false) SafetyResult.safe(arg, stats.get()) else SafetyResult.unsafe(trace, - arg, stats.get()) + override fun read( + reader: JsonReader + ): SafetyResult, Trace> { + initGson() + initTypes() + lateinit var arg: ARG + lateinit var stats: Optional + var safe: Boolean? = null + lateinit var trace: Trace + reader.beginObject() + while (reader.peek() != JsonToken.END_OBJECT) { + when (reader.nextName()) { + "arg" -> arg = gson.fromJson(reader, argType) + "stats" -> stats = gson.fromJson(reader, Optional::class.java) + "safe" -> safe = reader.nextBoolean() + "trace" -> trace = gson.fromJson(reader, traceType) + } } + reader.endObject() + return if (stats.isEmpty) + if (safe == true) SafetyResult.safe(arg) else SafetyResult.unsafe(trace, arg) + else if (safe == false) SafetyResult.safe(arg, stats.get()) + else SafetyResult.unsafe(trace, arg, stats.get()) + } - private fun initGson() { - if (!this::gson.isInitialized) gson = gsonSupplier() - } + private fun initGson() { + if (!this::gson.isInitialized) gson = gsonSupplier() + } - private fun initTypes() { - if (!this::traceType.isInitialized) traceType = traceTypeSupplier() - if (!this::argType.isInitialized) argType = argTypeSupplier() - } -} \ No newline at end of file + private fun initTypes() { + if (!this::traceType.isInitialized) traceType = traceTypeSupplier() + if (!this::argType.isInitialized) argType = argTypeSupplier() + } +} diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java index 4f2f998af5..f6609fdc97 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsExplTest.java @@ -15,18 +15,25 @@ */ package hu.bme.mit.theta.sts.analysis; +import static hu.bme.mit.theta.analysis.algorithm.arg.ArgUtils.isWellLabeled; +import static hu.bme.mit.theta.core.decl.Decls.Var; +import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.*; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.*; +import static org.junit.Assert.assertTrue; + import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; import hu.bme.mit.theta.analysis.algorithm.arg.ArgNodeComparators; -import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.expl.ExplAnalysis; import hu.bme.mit.theta.analysis.expl.ExplPrec; import hu.bme.mit.theta.analysis.expl.ExplState; @@ -34,12 +41,7 @@ import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.analysis.expr.ExprStatePredicate; -import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceChecker; -import hu.bme.mit.theta.analysis.expr.refinement.ExprTraceUnsatCoreChecker; -import hu.bme.mit.theta.analysis.expr.refinement.JoiningPrecRefiner; -import hu.bme.mit.theta.analysis.expr.refinement.PruneStrategy; -import hu.bme.mit.theta.analysis.expr.refinement.SingleExprTraceRefiner; -import hu.bme.mit.theta.analysis.expr.refinement.VarsRefutation; +import hu.bme.mit.theta.analysis.expr.refinement.*; import hu.bme.mit.theta.analysis.waitlist.PriorityWaitlist; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; @@ -52,23 +54,9 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory; import hu.bme.mit.theta.sts.STS; import hu.bme.mit.theta.sts.STS.Builder; -import org.junit.Test; - import java.util.Collections; import java.util.function.Predicate; - -import static hu.bme.mit.theta.analysis.algorithm.arg.ArgUtils.isWellLabeled; -import static hu.bme.mit.theta.core.decl.Decls.Var; -import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Imply; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Add; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Eq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Geq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Lt; -import static org.junit.Assert.assertTrue; +import org.junit.Test; public class StsExplTest { @@ -88,8 +76,10 @@ public void test() { builder.addInit(Eq(x, Int(0))); builder.addInit(Eq(y, Int(0))); - builder.addTrans(And(Imply(Lt(x, Int(mod)), Eq(Prime(x), Add(x, Int(1)))), - Imply(Geq(x, Int(mod)), Eq(Prime(x), Int(0))))); + builder.addTrans( + And( + Imply(Lt(x, Int(mod)), Eq(Prime(x), Add(x, Int(1)))), + Imply(Geq(x, Int(mod)), Eq(Prime(x), Int(0))))); builder.addTrans(Eq(Prime(y), Int(0))); builder.setProp(Not(Eq(x, Int(mod)))); @@ -98,40 +88,45 @@ public void test() { final Solver abstractionSolver = Z3LegacySolverFactory.getInstance().createSolver(); final UCSolver refinementSolver = Z3LegacySolverFactory.getInstance().createUCSolver(); - final Analysis analysis = ExplAnalysis.create( - abstractionSolver, sts.getInit()); - final Predicate target = new ExprStatePredicate(Not(sts.getProp()), - abstractionSolver); + final Analysis analysis = + ExplAnalysis.create(abstractionSolver, sts.getInit()); + final Predicate target = + new ExprStatePredicate(Not(sts.getProp()), abstractionSolver); final ExplPrec prec = ExplPrec.of(Collections.singleton(vy)); final LTS lts = StsLts.create(sts); - final ArgBuilder argBuilder = ArgBuilder.create(lts, - analysis, target); + final ArgBuilder argBuilder = + ArgBuilder.create(lts, analysis, target); - final ArgAbstractor abstractor = BasicArgAbstractor.builder( - argBuilder) - .waitlist(PriorityWaitlist.create(ArgNodeComparators.bfs())).logger(logger).build(); + final ArgAbstractor abstractor = + BasicArgAbstractor.builder(argBuilder) + .waitlist(PriorityWaitlist.create(ArgNodeComparators.bfs())) + .logger(logger) + .build(); - final ExprTraceChecker exprTraceChecker = ExprTraceUnsatCoreChecker.create( - sts.getInit(), - Not(sts.getProp()), refinementSolver); + final ExprTraceChecker exprTraceChecker = + ExprTraceUnsatCoreChecker.create( + sts.getInit(), Not(sts.getProp()), refinementSolver); - final SingleExprTraceRefiner refiner = SingleExprTraceRefiner - .create(exprTraceChecker, JoiningPrecRefiner.create(new VarsRefToExplPrec()), - PruneStrategy.LAZY, logger); + final SingleExprTraceRefiner refiner = + SingleExprTraceRefiner.create( + exprTraceChecker, + JoiningPrecRefiner.create(new VarsRefToExplPrec()), + PruneStrategy.LAZY, + logger); - final SafetyChecker, Trace, ExplPrec> checker = ArgCegarChecker.create( - abstractor, refiner, logger); + final SafetyChecker, Trace, ExplPrec> + checker = ArgCegarChecker.create(abstractor, refiner, logger); - final SafetyResult, Trace> safetyStatus = checker.check(prec); + final SafetyResult, Trace> safetyStatus = + checker.check(prec); - final ARG arg = safetyStatus.getWitness(); + final ARG arg = safetyStatus.getProof(); assertTrue(isWellLabeled(arg, abstractionSolver)); // System.out.println(new // GraphvizWriter().writeString(ArgVisualizer.visualize(arg))); } - } diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsMddCheckerTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsMddCheckerTest.java index e9f88faaad..929a01e400 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsMddCheckerTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsMddCheckerTest.java @@ -15,11 +15,13 @@ */ package hu.bme.mit.theta.sts.analysis; +import static org.junit.Assert.assertTrue; + import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.mdd.MddCex; import hu.bme.mit.theta.analysis.algorithm.mdd.MddChecker; import hu.bme.mit.theta.analysis.algorithm.mdd.MddChecker.IterationStrategy; -import hu.bme.mit.theta.analysis.algorithm.mdd.MddWitness; +import hu.bme.mit.theta.analysis.algorithm.mdd.MddProof; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.common.Utils; import hu.bme.mit.theta.common.logging.ConsoleLogger; @@ -35,16 +37,12 @@ import hu.bme.mit.theta.sts.aiger.AigerToSts; import hu.bme.mit.theta.sts.dsl.StsDslManager; import hu.bme.mit.theta.sts.dsl.StsSpec; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - import java.io.FileInputStream; -import java.io.IOException; import java.util.Arrays; import java.util.Collection; - -import static org.junit.Assert.assertTrue; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; @RunWith(value = Parameterized.class) public class StsMddCheckerTest { @@ -56,35 +54,23 @@ public class StsMddCheckerTest { @Parameterized.Parameters(name = "{index}: {0}, {1}") public static Collection data() { - return Arrays.asList(new Object[][]{ - {"src/test/resources/hw1_false.aag", false}, - - {"src/test/resources/hw2_true.aag", true}, - - {"src/test/resources/boolean1.system", false}, - - {"src/test/resources/boolean2.system", false}, - - {"src/test/resources/counter.system", true}, - - {"src/test/resources/counter_bad.system", false}, - - {"src/test/resources/counter_parametric.system", true}, - - {"src/test/resources/loop.system", true}, - - {"src/test/resources/loop_bad.system", false}, - - {"src/test/resources/multipleinitial.system", false}, - - {"src/test/resources/readerswriters.system", true}, - - {"src/test/resources/simple1.system", false}, - - {"src/test/resources/simple2.system", true}, - - {"src/test/resources/simple3.system", false}, - }); + return Arrays.asList( + new Object[][] { + {"src/test/resources/hw1_false.aag", false}, + {"src/test/resources/hw2_true.aag", true}, + {"src/test/resources/boolean1.system", false}, + {"src/test/resources/boolean2.system", false}, + {"src/test/resources/counter.system", true}, + {"src/test/resources/counter_bad.system", false}, + {"src/test/resources/counter_parametric.system", true}, + {"src/test/resources/loop.system", true}, + {"src/test/resources/loop_bad.system", false}, + {"src/test/resources/multipleinitial.system", false}, + {"src/test/resources/readerswriters.system", true}, + {"src/test/resources/simple1.system", false}, + {"src/test/resources/simple2.system", true}, + {"src/test/resources/simple3.system", false}, + }); } @Test @@ -100,19 +86,27 @@ public void test() throws Exception { sts = Utils.singleElementOf(spec.getAllSts()); } - final SafetyResult status; + final SafetyResult status; try (var solverPool = new SolverPool(Z3LegacySolverFactory.getInstance())) { - final MddChecker checker = MddChecker.create(sts.getInit(), VarIndexingFactory.indexing(0), new ExprAction() { - @Override - public Expr toExpr() { - return sts.getTrans(); - } - - @Override - public VarIndexing nextIndexing() { - return VarIndexingFactory.indexing(1); - } - }, sts.getProp(), solverPool, logger, IterationStrategy.GSAT); + final MddChecker checker = + MddChecker.create( + sts.getInit(), + VarIndexingFactory.indexing(0), + new ExprAction() { + @Override + public Expr toExpr() { + return sts.getTrans(); + } + + @Override + public VarIndexing nextIndexing() { + return VarIndexingFactory.indexing(1); + } + }, + sts.getProp(), + solverPool, + logger, + IterationStrategy.GSAT); status = checker.check(null); } @@ -122,5 +116,4 @@ public VarIndexing nextIndexing() { assertTrue(status.isUnsafe()); } } - } diff --git a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java index bed9497f54..5022d36401 100644 --- a/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java +++ b/subprojects/sts/sts-analysis/src/test/java/hu/bme/mit/theta/sts/analysis/StsPredTest.java @@ -18,53 +18,40 @@ import static hu.bme.mit.theta.analysis.algorithm.arg.ArgUtils.isWellLabeled; import static hu.bme.mit.theta.core.decl.Decls.Var; import static hu.bme.mit.theta.core.type.anytype.Exprs.Prime; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Imply; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Not; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Add; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Eq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Geq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Lt; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.*; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.*; import static org.junit.Assert.assertTrue; -import java.util.function.Predicate; - -import hu.bme.mit.theta.analysis.Trace; -import hu.bme.mit.theta.analysis.algorithm.SafetyResult; -import hu.bme.mit.theta.analysis.expr.refinement.*; -import hu.bme.mit.theta.solver.ItpSolver; -import hu.bme.mit.theta.solver.Solver; -import org.junit.Before; -import org.junit.Test; - import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.State; +import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; +import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgBuilder; -import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor; -import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker; +import hu.bme.mit.theta.analysis.algorithm.cegar.BasicArgAbstractor; import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.analysis.expr.ExprStatePredicate; -import hu.bme.mit.theta.analysis.pred.ExprSplitters; -import hu.bme.mit.theta.analysis.pred.ItpRefToPredPrec; -import hu.bme.mit.theta.analysis.pred.PredAbstractors; -import hu.bme.mit.theta.analysis.pred.PredAnalysis; -import hu.bme.mit.theta.analysis.pred.PredPrec; -import hu.bme.mit.theta.analysis.pred.PredState; +import hu.bme.mit.theta.analysis.expr.refinement.*; +import hu.bme.mit.theta.analysis.pred.*; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.core.type.inttype.IntType; +import hu.bme.mit.theta.solver.ItpSolver; +import hu.bme.mit.theta.solver.Solver; import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory; import hu.bme.mit.theta.sts.STS; import hu.bme.mit.theta.sts.STS.Builder; +import java.util.function.Predicate; +import org.junit.Before; +import org.junit.Test; public class StsPredTest { @@ -81,8 +68,10 @@ public void setUp() { final Builder builder = STS.builder(); builder.addInit(Eq(x, Int(0))); - builder.addTrans(And(Imply(Lt(x, Int(mod)), Eq(Prime(x), Add(x, Int(1)))), - Imply(Geq(x, Int(mod)), Eq(Prime(x), Int(0))))); + builder.addTrans( + And( + Imply(Lt(x, Int(mod)), Eq(Prime(x), Add(x, Int(1)))), + Imply(Geq(x, Int(mod)), Eq(Prime(x), Int(0))))); builder.setProp(Not(Eq(x, Int(mod)))); sts = builder.build(); @@ -91,39 +80,43 @@ public void setUp() { @Test public void testPredPrec() { - final Analysis analysis = PredAnalysis.create( - abstractionSolver, - PredAbstractors.booleanSplitAbstractor(abstractionSolver), sts.getInit()); - final Predicate target = new ExprStatePredicate(Not(sts.getProp()), - abstractionSolver); + final Analysis analysis = + PredAnalysis.create( + abstractionSolver, + PredAbstractors.booleanSplitAbstractor(abstractionSolver), + sts.getInit()); + final Predicate target = + new ExprStatePredicate(Not(sts.getProp()), abstractionSolver); final PredPrec prec = PredPrec.of(); final LTS lts = StsLts.create(sts); - final ArgBuilder argBuilder = ArgBuilder.create(lts, - analysis, target); + final ArgBuilder argBuilder = + ArgBuilder.create(lts, analysis, target); - final ArgAbstractor abstractor = BasicArgAbstractor.builder( - argBuilder).logger(logger) - .build(); + final ArgAbstractor abstractor = + BasicArgAbstractor.builder(argBuilder).logger(logger).build(); - final ExprTraceChecker exprTraceChecker = ExprTraceFwBinItpChecker.create( - sts.getInit(), - Not(sts.getProp()), refinementSolver); + final ExprTraceChecker exprTraceChecker = + ExprTraceFwBinItpChecker.create( + sts.getInit(), Not(sts.getProp()), refinementSolver); - final SingleExprTraceRefiner refiner = SingleExprTraceRefiner - .create(exprTraceChecker, + final SingleExprTraceRefiner refiner = + SingleExprTraceRefiner.create( + exprTraceChecker, JoiningPrecRefiner.create(new ItpRefToPredPrec(ExprSplitters.atoms())), - PruneStrategy.LAZY, logger); + PruneStrategy.LAZY, + logger); - final SafetyChecker, Trace, PredPrec> checker = ArgCegarChecker.create( - abstractor, refiner, logger); + final SafetyChecker, Trace, PredPrec> + checker = ArgCegarChecker.create(abstractor, refiner, logger); - final SafetyResult, Trace> safetyStatus = checker.check(prec); + final SafetyResult, Trace> safetyStatus = + checker.check(prec); System.out.println(safetyStatus); - final ARG arg = safetyStatus.getWitness(); + final ARG arg = safetyStatus.getProof(); assertTrue(isWellLabeled(arg, abstractionSolver)); // System.out.println(new diff --git a/subprojects/sts/sts-cli/src/main/java/hu/bme/mit/theta/sts/cli/StsCli.java b/subprojects/sts/sts-cli/src/main/java/hu/bme/mit/theta/sts/cli/StsCli.java index ddb48470eb..884bfabdae 100644 --- a/subprojects/sts/sts-cli/src/main/java/hu/bme/mit/theta/sts/cli/StsCli.java +++ b/subprojects/sts/sts-cli/src/main/java/hu/bme/mit/theta/sts/cli/StsCli.java @@ -52,26 +52,14 @@ import hu.bme.mit.theta.sts.analysis.StsTraceConcretizer; import hu.bme.mit.theta.sts.analysis.config.StsConfig; import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder; -import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder.Domain; -import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder.InitPrec; -import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder.PredSplit; -import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder.Refinement; -import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder.Search; +import hu.bme.mit.theta.sts.analysis.config.StsConfigBuilder.*; import hu.bme.mit.theta.sts.dsl.StsDslManager; import hu.bme.mit.theta.sts.dsl.StsSpec; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.io.*; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; -/** - * A command line interface for running a CEGAR configuration on an STS. - */ +/** A command line interface for running a CEGAR configuration on an STS. */ public class StsCli { private static final String JAR_NAME = "theta-sts-cli.jar"; @@ -85,41 +73,64 @@ enum Algorithm { IMC } - @Parameter(names = {"--domain"}, description = "Abstract domain") + @Parameter( + names = {"--domain"}, + description = "Abstract domain") Domain domain = Domain.PRED_CART; - @Parameter(names = {"--algorithm"}, description = "Algorithm") + @Parameter( + names = {"--algorithm"}, + description = "Algorithm") Algorithm algorithm = Algorithm.CEGAR; - @Parameter(names = {"--refinement"}, description = "Refinement strategy") + @Parameter( + names = {"--refinement"}, + description = "Refinement strategy") Refinement refinement = Refinement.SEQ_ITP; - @Parameter(names = {"--search"}, description = "Search strategy") + @Parameter( + names = {"--search"}, + description = "Search strategy") Search search = Search.BFS; - @Parameter(names = {"--predsplit"}, description = "Predicate splitting") + @Parameter( + names = {"--predsplit"}, + description = "Predicate splitting") PredSplit predSplit = PredSplit.WHOLE; - @Parameter(names = {"--model"}, description = "Path of the input STS model", required = true) + @Parameter( + names = {"--model"}, + description = "Path of the input STS model", + required = true) String model; - @Parameter(names = {"--initprec"}, description = "Initial precision") + @Parameter( + names = {"--initprec"}, + description = "Initial precision") InitPrec initPrec = InitPrec.EMPTY; - @Parameter(names = "--prunestrategy", description = "Strategy for pruning the ARG after refinement") + @Parameter( + names = "--prunestrategy", + description = "Strategy for pruning the ARG after refinement") PruneStrategy pruneStrategy = PruneStrategy.LAZY; - @Parameter(names = {"--loglevel"}, description = "Detailedness of logging") + @Parameter( + names = {"--loglevel"}, + description = "Detailedness of logging") Logger.Level logLevel = Level.SUBSTEP; - @Parameter(names = {"--benchmark"}, description = "Benchmark mode (only print metrics)") + @Parameter( + names = {"--benchmark"}, + description = "Benchmark mode (only print metrics)") Boolean benchmarkMode = false; @Parameter(names = "--cex", description = "Write concrete counterexample to a file") String cexfile = null; - @Parameter(names = { - "--header"}, description = "Print only a header (for benchmarks)", help = true) + @Parameter( + names = {"--header"}, + description = "Print only a header (for benchmarks)", + help = true) boolean headerOnly = false; @Parameter(names = "--stacktrace", description = "Print full stack trace in case of exception") @@ -169,11 +180,15 @@ private void run() { if (algorithm.equals(Algorithm.CEGAR)) { final StsConfig configuration = buildConfiguration(sts); status = check(configuration); - } else if (algorithm == Algorithm.BMC || algorithm == Algorithm.KINDUCTION || algorithm == Algorithm.IMC) { - final BoundedChecker checker = buildBoundedChecker(sts, Z3LegacySolverFactory.getInstance()); + } else if (algorithm == Algorithm.BMC + || algorithm == Algorithm.KINDUCTION + || algorithm == Algorithm.IMC) { + final BoundedChecker checker = + buildBoundedChecker(sts, Z3LegacySolverFactory.getInstance()); status = checker.check(null); } else { - throw new UnsupportedOperationException("Algorithm " + algorithm + " not supported"); + throw new UnsupportedOperationException( + "Algorithm " + algorithm + " not supported"); } sw.stop(); printResult(status, sts, sw.elapsed(TimeUnit.MILLISECONDS)); @@ -186,20 +201,35 @@ private void run() { } } - private SafetyResult, ? extends Trace> check(StsConfig configuration) throws Exception { + private SafetyResult, ? extends Trace> check( + StsConfig configuration) throws Exception { try { return configuration.check(); } catch (final Exception ex) { String message = ex.getMessage() == null ? "(no message)" : ex.getMessage(); throw new Exception( - "Error while running algorithm: " + ex.getClass().getSimpleName() + " " + message, + "Error while running algorithm: " + + ex.getClass().getSimpleName() + + " " + + message, ex); } } private void printHeader() { - Stream.of("Result", "TimeMs", "AlgoTimeMs", "AbsTimeMs", "RefTimeMs", "Iterations", - "ArgSize", "ArgDepth", "ArgMeanBranchFactor", "CexLen", "Vars", "Size") + Stream.of( + "Result", + "TimeMs", + "AlgoTimeMs", + "AbsTimeMs", + "RefTimeMs", + "Iterations", + "ArgSize", + "ArgDepth", + "ArgMeanBranchFactor", + "CexLen", + "Vars", + "Size") .forEach(writer::cell); writer.newRow(); } @@ -228,49 +258,64 @@ private STS loadModel() throws Exception { private StsConfig buildConfiguration(final STS sts) throws Exception { try { return new StsConfigBuilder(domain, refinement, Z3LegacySolverFactory.getInstance()) - .initPrec(initPrec).search(search) - .predSplit(predSplit).pruneStrategy(pruneStrategy).logger(logger).build(sts); + .initPrec(initPrec) + .search(search) + .predSplit(predSplit) + .pruneStrategy(pruneStrategy) + .logger(logger) + .build(sts); } catch (final Exception ex) { throw new Exception("Could not create configuration: " + ex.getMessage(), ex); } } - private BoundedChecker buildBoundedChecker(final STS sts, final SolverFactory abstractionSolverFactory) { + private BoundedChecker buildBoundedChecker( + final STS sts, final SolverFactory abstractionSolverFactory) { final MonolithicExpr monolithicExpr = StsToMonolithicExprKt.toMonolithicExpr(sts); final BoundedChecker checker; switch (algorithm) { - case BMC -> checker = BoundedCheckerBuilderKt.buildBMC( - monolithicExpr, - abstractionSolverFactory.createSolver(), - val -> StsToMonolithicExprKt.valToState(sts, val), - (val1, val2) -> StsToMonolithicExprKt.valToAction(sts, val1, val2), - logger - ); - case KINDUCTION -> checker = BoundedCheckerBuilderKt.buildKIND( - monolithicExpr, - abstractionSolverFactory.createSolver(), - abstractionSolverFactory.createSolver(), - val -> StsToMonolithicExprKt.valToState(sts, val), - (val1, val2) -> StsToMonolithicExprKt.valToAction(sts, val1, val2), - logger - ); - case IMC -> checker = BoundedCheckerBuilderKt.buildIMC( - monolithicExpr, - abstractionSolverFactory.createSolver(), - abstractionSolverFactory.createItpSolver(), - val -> StsToMonolithicExprKt.valToState(sts, val), - (val1, val2) -> StsToMonolithicExprKt.valToAction(sts, val1, val2), - logger - ); + case BMC -> + checker = + BoundedCheckerBuilderKt.buildBMC( + monolithicExpr, + abstractionSolverFactory.createSolver(), + val -> StsToMonolithicExprKt.valToState(sts, val), + (val1, val2) -> + StsToMonolithicExprKt.valToAction(sts, val1, val2), + logger); + case KINDUCTION -> + checker = + BoundedCheckerBuilderKt.buildKIND( + monolithicExpr, + abstractionSolverFactory.createSolver(), + abstractionSolverFactory.createSolver(), + val -> StsToMonolithicExprKt.valToState(sts, val), + (val1, val2) -> + StsToMonolithicExprKt.valToAction(sts, val1, val2), + logger); + case IMC -> + checker = + BoundedCheckerBuilderKt.buildIMC( + monolithicExpr, + abstractionSolverFactory.createSolver(), + abstractionSolverFactory.createItpSolver(), + val -> StsToMonolithicExprKt.valToState(sts, val), + (val1, val2) -> + StsToMonolithicExprKt.valToAction(sts, val1, val2), + logger); default -> - throw new UnsupportedOperationException("Algorithm " + algorithm + " not supported"); + throw new UnsupportedOperationException( + "Algorithm " + algorithm + " not supported"); } return checker; } - private void printResult(final SafetyResult> status, final STS sts, - final long totalTimeMs) { - final CegarStatistics stats = (CegarStatistics) status.getStats().orElse(new CegarStatistics(0, 0, 0, 0)); + private void printResult( + final SafetyResult> status, + final STS sts, + final long totalTimeMs) { + final CegarStatistics stats = + (CegarStatistics) status.getStats().orElse(new CegarStatistics(0, 0, 0, 0)); if (benchmarkMode) { writer.cell(status.isSafe()); writer.cell(totalTimeMs); @@ -278,7 +323,7 @@ private void printResult(final SafetyResult> status, fi writer.cell(stats.getAbstractorTimeMs()); writer.cell(stats.getRefinerTimeMs()); writer.cell(stats.getIterations()); - if (status.getWitness() instanceof ARG arg) { + if (status.getProof() instanceof ARG arg) { writer.cell(arg.size()); writer.cell(arg.getDepth()); writer.cell(arg.getMeanBranchingFactor()); @@ -304,7 +349,10 @@ private void printError(final Throwable ex) { writer.cell("[EX] " + ex.getClass().getSimpleName() + ": " + message); writer.newRow(); } else { - logger.write(Level.RESULT, "%s occurred, message: %s%n", ex.getClass().getSimpleName(), + logger.write( + Level.RESULT, + "%s occurred, message: %s%n", + ex.getClass().getSimpleName(), message); if (stacktrace) { final StringWriter errors = new StringWriter(); @@ -318,9 +366,10 @@ private void printError(final Throwable ex) { private void writeCex(final STS sts, final SafetyResult.Unsafe> status) throws FileNotFoundException { - @SuppressWarnings("unchecked") final Trace trace = (Trace) status.getCex(); - final Trace concrTrace = StsTraceConcretizer.concretize(sts, trace, - Z3LegacySolverFactory.getInstance()); + @SuppressWarnings("unchecked") + final Trace trace = (Trace) status.getCex(); + final Trace concrTrace = + StsTraceConcretizer.concretize(sts, trace, Z3LegacySolverFactory.getInstance()); final File file = new File(cexfile); PrintWriter printWriter = null; try { diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/oc/XcfaOcChecker.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/oc/XcfaOcChecker.kt index 6ffa9bc1fb..72f7a2520e 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/oc/XcfaOcChecker.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/oc/XcfaOcChecker.kt @@ -13,15 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.analysis.oc -import hu.bme.mit.theta.analysis.EmptyCex import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult -import hu.bme.mit.theta.analysis.algorithm.arg.ARG import hu.bme.mit.theta.analysis.algorithm.oc.EventType import hu.bme.mit.theta.analysis.algorithm.oc.OcChecker import hu.bme.mit.theta.analysis.algorithm.oc.Relation @@ -52,335 +49,363 @@ import hu.bme.mit.theta.xcfa.passes.AssumeFalseRemovalPass import hu.bme.mit.theta.xcfa.passes.AtomicReadsOneWritePass import hu.bme.mit.theta.xcfa.passes.MutexToVarPass -private val Expr<*>.vars get() = ExprUtils.getVars(this) +private val Expr<*>.vars + get() = ExprUtils.getVars(this) -class XcfaOcChecker(xcfa: XCFA, decisionProcedure: OcDecisionProcedureType, private val logger: Logger) : - SafetyChecker>, XcfaAction>, XcfaPrec> { +class XcfaOcChecker( + xcfa: XCFA, + decisionProcedure: OcDecisionProcedureType, + private val logger: Logger, +) : SafetyChecker>, XcfaAction>, XcfaPrec> { - private val ocChecker: OcChecker = decisionProcedure.checker() - private val solver = ocChecker.solver + private val ocChecker: OcChecker = decisionProcedure.checker() + private val solver = ocChecker.solver - private val xcfa: XCFA = xcfa.optimizeFurther( - listOf(AssumeFalseRemovalPass(), MutexToVarPass(), AtomicReadsOneWritePass()) + private val xcfa: XCFA = + xcfa.optimizeFurther( + listOf(AssumeFalseRemovalPass(), MutexToVarPass(), AtomicReadsOneWritePass()) ) - private var indexing = VarIndexingFactory.indexing(0) - private val localVars = mutableMapOf, MutableMap>>() - - private val threads = mutableSetOf() - private val events = mutableMapOf, MutableMap>>() - private val violations = mutableListOf() // OR! - private val branchingConditions = mutableListOf>() - private val pos = mutableListOf() - private val rfs = mutableMapOf, MutableSet>() - - override fun check( - prec: XcfaPrec?): SafetyResult>, XcfaAction>> = let { - if (xcfa.initProcedures.size > 1) error("Multiple entry points are not supported by OC checker.") + private var indexing = VarIndexingFactory.indexing(0) + private val localVars = mutableMapOf, MutableMap>>() + + private val threads = mutableSetOf() + private val events = mutableMapOf, MutableMap>>() + private val violations = mutableListOf() // OR! + private val branchingConditions = mutableListOf>() + private val pos = mutableListOf() + private val rfs = mutableMapOf, MutableSet>() + + override fun check( + prec: XcfaPrec? + ): SafetyResult>, XcfaAction>> = + let { + if (xcfa.initProcedures.size > 1) + error("Multiple entry points are not supported by OC checker.") logger.write(Logger.Level.MAINSTEP, "Adding constraints...\n") xcfa.initProcedures.forEach { processThread(Thread(it.first)) } addCrossThreadRelations() - if (!addToSolver()) return@let SafetyResult.safe>, XcfaAction>>( - EmptyWitness.getInstance()) // no violations in the model + if (!addToSolver()) + return@let SafetyResult.safe>, XcfaAction>>( + EmptyProof.getInstance() + ) // no violations in the model logger.write(Logger.Level.MAINSTEP, "Start checking...\n") val status = ocChecker.check(events, pos, rfs) when { - status?.isUnsat == true -> SafetyResult.safe(EmptyWitness.getInstance()) - status?.isSat == true -> SafetyResult.unsafe( - XcfaOcTraceExtractor(xcfa, ocChecker, threads, events, violations, pos).trace, - EmptyWitness.getInstance() + status?.isUnsat == true -> SafetyResult.safe(EmptyProof.getInstance()) + status?.isSat == true -> + SafetyResult.unsafe( + XcfaOcTraceExtractor(xcfa, ocChecker, threads, events, violations, pos).trace, + EmptyProof.getInstance(), ) - else -> SafetyResult.unknown() + else -> SafetyResult.unknown() } - }.also { logger.write(Logger.Level.MAINSTEP, "OC checker result: $it\n") } - - private fun processThread(thread: Thread): List { - threads.add(thread) - val pid = thread.pid - var last = listOf() - var guard = setOf>() - lateinit var lastWrites: MutableMap, Set> - lateinit var edge: XcfaEdge - var inEdge = false - var atomicEntered: Boolean? = null - - val newEvent: (VarDecl<*>, EventType) -> List = { d, type -> - check(!inEdge || last.size == 1) - val decl = d.threadVar(pid) - val useLastClk = inEdge || atomicEntered == true - val e = - if (useLastClk) E(decl.getNewIndexed(), type, guard, pid, edge, last.first().clkId) - else E(decl.getNewIndexed(), type, guard, pid, edge) - last.forEach { po(it, e) } - inEdge = true - if (atomicEntered == false) atomicEntered = true - when (type) { - EventType.READ -> lastWrites[decl]?.forEach { rfs.add(RelationType.RF, it, e) } - EventType.WRITE -> lastWrites[decl] = setOf(e) - } - events[decl] = (events[decl] ?: mutableMapOf()).apply { - this[pid] = (this[pid] ?: mutableListOf()).apply { add(e) } - } - listOf(e) + } + .also { logger.write(Logger.Level.MAINSTEP, "OC checker result: $it\n") } + + private fun processThread(thread: Thread): List { + threads.add(thread) + val pid = thread.pid + var last = listOf() + var guard = setOf>() + lateinit var lastWrites: MutableMap, Set> + lateinit var edge: XcfaEdge + var inEdge = false + var atomicEntered: Boolean? = null + + val newEvent: (VarDecl<*>, EventType) -> List = { d, type -> + check(!inEdge || last.size == 1) + val decl = d.threadVar(pid) + val useLastClk = inEdge || atomicEntered == true + val e = + if (useLastClk) E(decl.getNewIndexed(), type, guard, pid, edge, last.first().clkId) + else E(decl.getNewIndexed(), type, guard, pid, edge) + last.forEach { po(it, e) } + inEdge = true + if (atomicEntered == false) atomicEntered = true + when (type) { + EventType.READ -> lastWrites[decl]?.forEach { rfs.add(RelationType.RF, it, e) } + EventType.WRITE -> lastWrites[decl] = setOf(e) + } + events[decl] = + (events[decl] ?: mutableMapOf()).apply { + this[pid] = (this[pid] ?: mutableListOf()).apply { add(e) } } + listOf(e) + } - val waitList = mutableSetOf() - val toVisit = mutableSetOf(SearchItem(thread.procedure.initLoc).apply { - guards.add(thread.guard) - thread.startEvent?.let { lastEvents.add(it) } - this.lastWrites.add(thread.lastWrites) - }) - val threads = mutableListOf() - - while (toVisit.isNotEmpty()) { - val current = toVisit.first() - toVisit.remove(current) - check(current.incoming == current.loc.incomingEdges.size) - check(current.incoming == current.guards.size || current.loc.initial) - // lastEvents intentionally skipped - check(current.incoming == current.lastWrites.size || current.loc.initial) - check(current.incoming == current.threadLookups.size) - check(current.incoming == current.atomics.size) - check(current.atomics.all { it == current.atomics.first() }) // bad pattern otherwise - - if (current.loc.error) { - val errorGuard = Or(current.lastEvents.map { it.guard.toAnd() }) - violations.add(Violation(current.loc, pid, errorGuard, current.lastEvents)) - continue - } - - if (current.loc.final) { - thread.finalEvents.addAll(current.lastEvents) + val waitList = mutableSetOf() + val toVisit = + mutableSetOf( + SearchItem(thread.procedure.initLoc).apply { + guards.add(thread.guard) + thread.startEvent?.let { lastEvents.add(it) } + this.lastWrites.add(thread.lastWrites) + } + ) + val threads = mutableListOf() + + while (toVisit.isNotEmpty()) { + val current = toVisit.first() + toVisit.remove(current) + check(current.incoming == current.loc.incomingEdges.size) + check(current.incoming == current.guards.size || current.loc.initial) + // lastEvents intentionally skipped + check(current.incoming == current.lastWrites.size || current.loc.initial) + check(current.incoming == current.threadLookups.size) + check(current.incoming == current.atomics.size) + check(current.atomics.all { it == current.atomics.first() }) // bad pattern otherwise + + if (current.loc.error) { + val errorGuard = Or(current.lastEvents.map { it.guard.toAnd() }) + violations.add(Violation(current.loc, pid, errorGuard, current.lastEvents)) + continue + } + + if (current.loc.final) { + thread.finalEvents.addAll(current.lastEvents) + } + + val mergedGuard = current.guards.toOrInSet() + val assumeConsts = mutableMapOf, MutableList>>() + + for (e in current.loc.outgoingEdges) { + edge = e + inEdge = false + last = current.lastEvents + // intersection of guards of incoming edges: + guard = mergedGuard + lastWrites = current.lastWrites.merge().toMutableMap() + val threadLookup = + current.threadLookups + .merge { s1, s2 -> + s1 + s2.filter { (guard2, _) -> s1.none { (guard1, _) -> guard1 == guard2 } } } + .toMutableMap() + var firstLabel = true + atomicEntered = current.atomics.firstOrNull() + + edge.getFlatLabels().forEach { label -> + if (label.references.isNotEmpty() || label.dereferences.isNotEmpty()) { + error("References not supported by OC checker.") + } + when (label) { + is StmtLabel -> { + when (val stmt = label.stmt) { + is AssignStmt<*> -> { + val consts = mutableMapOf, ConstDecl<*>>() + stmt.expr.vars.forEach { + last = newEvent(it, EventType.READ) + consts[it] = last.first().const + } + last = newEvent(stmt.varDecl, EventType.WRITE) + last.first().assignment = Eq(last.first().const.ref, stmt.expr.withConsts(consts)) + } - val mergedGuard = current.guards.toOrInSet() - val assumeConsts = mutableMapOf, MutableList>>() - - for (e in current.loc.outgoingEdges) { - edge = e - inEdge = false - last = current.lastEvents - // intersection of guards of incoming edges: - guard = mergedGuard - lastWrites = current.lastWrites.merge().toMutableMap() - val threadLookup = current.threadLookups.merge { s1, s2 -> - s1 + s2.filter { (guard2, _) -> s1.none { (guard1, _) -> guard1 == guard2 } } - }.toMutableMap() - var firstLabel = true - atomicEntered = current.atomics.firstOrNull() - - edge.getFlatLabels().forEach { label -> - if (label.references.isNotEmpty() || label.dereferences.isNotEmpty()) { - error("References not supported by OC checker.") - } - when (label) { - is StmtLabel -> { - when (val stmt = label.stmt) { - is AssignStmt<*> -> { - val consts = mutableMapOf, ConstDecl<*>>() - stmt.expr.vars.forEach { - last = newEvent(it, EventType.READ) - consts[it] = last.first().const - } - last = newEvent(stmt.varDecl, EventType.WRITE) - last.first().assignment = Eq(last.first().const.ref, stmt.expr.withConsts(consts)) - } - - is AssumeStmt -> { - val consts = stmt.cond.vars.associateWith { it.threadVar(pid).getNewIndexed(false) } - val condWithConsts = stmt.cond.withConsts(consts) - val asAssign = consts.size == 1 && consts.keys.first().threadVar(pid) !in lastWrites - if (edge.source.outgoingEdges.size > 1 || !asAssign) { - guard = guard + condWithConsts - if (firstLabel) { - consts.forEach { (v, c) -> - assumeConsts.getOrPut(v) { mutableListOf() }.add(c) - } - } - } - stmt.cond.vars.forEach { - last = newEvent(it, EventType.READ) - } - if (edge.source.outgoingEdges.size == 1 && asAssign) { - last.first().assignment = condWithConsts - } - } - - is HavocStmt<*> -> { - last = newEvent(stmt.varDecl, EventType.WRITE) - } - - else -> error("Unsupported statement type: $stmt") - } - } - - is StartLabel -> { - // TODO StartLabel params - if (label.name in thread.startHistory) { - error("Recursive thread start not supported by OC checker.") - } - val procedure = xcfa.procedures.find { it.name == label.name } - ?: error("Procedure not found: ${label.name}") - last = newEvent(label.pidVar, EventType.WRITE) - val pidVar = label.pidVar.threadVar(pid) - if (this.threads.any { it.pidVar == pidVar }) { - error("Using a pthread_t variable in multiple threads is not supported by OC checker.") - } - val newHistory = thread.startHistory + thread.procedure.name - val newThread = Thread(procedure, guard, pidVar, last.first(), newHistory, lastWrites) - last.first().assignment = Eq(last.first().const.ref, Int(newThread.pid)) - threadLookup[pidVar] = setOf(Pair(guard, newThread)) - processThread(newThread) - } - - is JoinLabel -> { - val incomingGuard = guard - val lastEvents = mutableListOf() - val joinGuards = mutableListOf>>() - threadLookup[label.pidVar.threadVar(pid)]?.forEach { (g, thread) -> - guard = incomingGuard + g + thread.finalEvents.map { it.guard }.toOrInSet() - val joinEvent = newEvent(label.pidVar, EventType.READ).first() - thread.finalEvents.forEach { final -> po(final, joinEvent) } - lastEvents.add(joinEvent) - joinGuards.add(guard) - } ?: error("Thread started in a different thread: not supported by OC checker.") - guard = joinGuards.toOrInSet() - last = lastEvents - } - - is FenceLabel -> { - if (label.labels.size > 1 || label.labels.firstOrNull()?.contains("ATOMIC") != true) { - error("Untransformed fence label: $label") - } - if (label.isAtomicBegin) atomicEntered = false - if (label.isAtomicEnd) atomicEntered = null - } - - is NopLabel -> {} - else -> error("Unsupported label type by OC checker: $label") + is AssumeStmt -> { + val consts = + stmt.cond.vars.associateWith { it.threadVar(pid).getNewIndexed(false) } + val condWithConsts = stmt.cond.withConsts(consts) + val asAssign = + consts.size == 1 && consts.keys.first().threadVar(pid) !in lastWrites + if (edge.source.outgoingEdges.size > 1 || !asAssign) { + guard = guard + condWithConsts + if (firstLabel) { + consts.forEach { (v, c) -> + assumeConsts.getOrPut(v) { mutableListOf() }.add(c) + } } - firstLabel = false + } + stmt.cond.vars.forEach { last = newEvent(it, EventType.READ) } + if (edge.source.outgoingEdges.size == 1 && asAssign) { + last.first().assignment = condWithConsts + } } - val searchItem = waitList.find { it.loc == edge.target } - ?: SearchItem(edge.target).apply { waitList.add(this) } - searchItem.guards.add(guard) - searchItem.lastEvents.addAll(last) - searchItem.lastWrites.add(lastWrites) - searchItem.threadLookups.add(threadLookup) - searchItem.atomics.add(atomicEntered) - searchItem.incoming++ - if (searchItem.incoming == searchItem.loc.incomingEdges.size) { - waitList.remove(searchItem) - toVisit.add(searchItem) + is HavocStmt<*> -> { + last = newEvent(stmt.varDecl, EventType.WRITE) } - } - if (current.loc.outgoingEdges.size > 1) { - for (e in current.loc.outgoingEdges) { - val first = e.getFlatLabels().first() - if (first !is StmtLabel || first.stmt !is AssumeStmt) { - error("Branching with non-assume labels not supported by OC checker.") - } - } - assumeConsts.forEach { (_, set) -> - for ((i1, v1) in set.withIndex()) - for ((i2, v2) in set.withIndex()) { - if (i1 == i2) break - branchingConditions.add(Eq(v1.ref, v2.ref)) - } - } + else -> error("Unsupported statement type: $stmt") + } } - } - if (waitList.isNotEmpty()) error("Loops and dangling edges not supported by OC checker.") - return threads - } + is StartLabel -> { + // TODO StartLabel params + if (label.name in thread.startHistory) { + error("Recursive thread start not supported by OC checker.") + } + val procedure = + xcfa.procedures.find { it.name == label.name } + ?: error("Procedure not found: ${label.name}") + last = newEvent(label.pidVar, EventType.WRITE) + val pidVar = label.pidVar.threadVar(pid) + if (this.threads.any { it.pidVar == pidVar }) { + error( + "Using a pthread_t variable in multiple threads is not supported by OC checker." + ) + } + val newHistory = thread.startHistory + thread.procedure.name + val newThread = Thread(procedure, guard, pidVar, last.first(), newHistory, lastWrites) + last.first().assignment = Eq(last.first().const.ref, Int(newThread.pid)) + threadLookup[pidVar] = setOf(Pair(guard, newThread)) + processThread(newThread) + } - private fun addCrossThreadRelations() { - for ((_, map) in events) - for ((pid1, list1) in map) - for ((pid2, list2) in map) - if (pid1 != pid2) - for (e1 in list1.filter { it.type == EventType.WRITE }) - for (e2 in list2.filter { it.type == EventType.READ }) - rfs.add(RelationType.RF, e1, e2) - } + is JoinLabel -> { + val incomingGuard = guard + val lastEvents = mutableListOf() + val joinGuards = mutableListOf>>() + threadLookup[label.pidVar.threadVar(pid)]?.forEach { (g, thread) -> + guard = incomingGuard + g + thread.finalEvents.map { it.guard }.toOrInSet() + val joinEvent = newEvent(label.pidVar, EventType.READ).first() + thread.finalEvents.forEach { final -> po(final, joinEvent) } + lastEvents.add(joinEvent) + joinGuards.add(guard) + } ?: error("Thread started in a different thread: not supported by OC checker.") + guard = joinGuards.toOrInSet() + last = lastEvents + } - private fun addToSolver(): Boolean { - if (violations.isEmpty()) return false + is FenceLabel -> { + if (label.labels.size > 1 || label.labels.firstOrNull()?.contains("ATOMIC") != true) { + error("Untransformed fence label: $label") + } + if (label.isAtomicBegin) atomicEntered = false + if (label.isAtomicEnd) atomicEntered = null + } - // Value assignment - events.values.flatMap { it.values.flatten() }.filter { it.assignment != null }.forEach { event -> - if (event.guard.isEmpty()) solver.add(event.assignment) - else solver.add(Imply(event.guardExpr, event.assignment)) + is NopLabel -> {} + else -> error("Unsupported label type by OC checker: $label") + } + firstLabel = false } - // Branching conditions - branchingConditions.forEach { solver.add(it) } - - // Property violation - solver.add(Or(violations.map { it.guard })) - - // RF - rfs.forEach { (_, list) -> - list.groupBy { it.to }.forEach { (event, rels) -> - rels.forEach { rel -> - solver.add( - Imply( - rel.declRef, - And(rel.from.guardExpr, rel.to.guardExpr, Eq(rel.from.const.ref, rel.to.const.ref)) - ) - ) // RF-Val - } - solver.add(Imply(event.guardExpr, Or(rels.map { it.declRef }))) // RF-Some - } + val searchItem = + waitList.find { it.loc == edge.target } + ?: SearchItem(edge.target).apply { waitList.add(this) } + searchItem.guards.add(guard) + searchItem.lastEvents.addAll(last) + searchItem.lastWrites.add(lastWrites) + searchItem.threadLookups.add(threadLookup) + searchItem.atomics.add(atomicEntered) + searchItem.incoming++ + if (searchItem.incoming == searchItem.loc.incomingEdges.size) { + waitList.remove(searchItem) + toVisit.add(searchItem) } - - return true - } - - // Utility functions - - private fun po(from: E?, to: E) { - from ?: return - pos.add(Relation(RelationType.PO, from, to)) + } + + if (current.loc.outgoingEdges.size > 1) { + for (e in current.loc.outgoingEdges) { + val first = e.getFlatLabels().first() + if (first !is StmtLabel || first.stmt !is AssumeStmt) { + error("Branching with non-assume labels not supported by OC checker.") + } + } + assumeConsts.forEach { (_, set) -> + for ((i1, v1) in set.withIndex()) for ((i2, v2) in set.withIndex()) { + if (i1 == i2) break + branchingConditions.add(Eq(v1.ref, v2.ref)) + } + } + } } - private fun List>>.merge(merge: (Set, Set) -> Set = { a, b -> a + b }) = - reduce(mapOf()) { acc, map -> - (acc.keys + map.keys).associateWith { k -> - val set1 = acc[k] ?: setOf() - val set2 = map[k] ?: setOf() - merge(set1, set2) - } + if (waitList.isNotEmpty()) error("Loops and dangling edges not supported by OC checker.") + return threads + } + + private fun addCrossThreadRelations() { + for ((_, map) in events) for ((pid1, list1) in map) for ((pid2, list2) in map) if (pid1 != pid2) + for (e1 in list1.filter { it.type == EventType.WRITE }) for (e2 in + list2.filter { it.type == EventType.READ }) rfs.add(RelationType.RF, e1, e2) + } + + private fun addToSolver(): Boolean { + if (violations.isEmpty()) return false + + // Value assignment + events.values + .flatMap { it.values.flatten() } + .filter { it.assignment != null } + .forEach { event -> + if (event.guard.isEmpty()) solver.add(event.assignment) + else solver.add(Imply(event.guardExpr, event.assignment)) + } + + // Branching conditions + branchingConditions.forEach { solver.add(it) } + + // Property violation + solver.add(Or(violations.map { it.guard })) + + // RF + rfs.forEach { (_, list) -> + list + .groupBy { it.to } + .forEach { (event, rels) -> + rels.forEach { rel -> + solver.add( + Imply( + rel.declRef, + And(rel.from.guardExpr, rel.to.guardExpr, Eq(rel.from.const.ref, rel.to.const.ref)), + ) + ) // RF-Val + } + solver.add(Imply(event.guardExpr, Or(rels.map { it.declRef }))) // RF-Some } + } - private inline fun Collection.reduce(default: T, operation: (T, T) -> T): T = - if (isEmpty()) default else reduce(operation) + return true + } + + // Utility functions + + private fun po(from: E?, to: E) { + from ?: return + pos.add(Relation(RelationType.PO, from, to)) + } + + private fun List>>.merge( + merge: (Set, Set) -> Set = { a, b -> a + b } + ) = + reduce(mapOf()) { acc, map -> + (acc.keys + map.keys).associateWith { k -> + val set1 = acc[k] ?: setOf() + val set2 = map[k] ?: setOf() + merge(set1, set2) + } + } - private fun MutableMap, MutableSet>.add(type: RelationType, from: E, to: E) = - getOrPut(from.const.varDecl) { mutableSetOf() }.add(Relation(type, from, to)) + private inline fun Collection.reduce(default: T, operation: (T, T) -> T): T = + if (isEmpty()) default else reduce(operation) - private fun Expr.withConsts(varToConst: Map, ConstDecl<*>>): Expr { - if (this is RefExpr) { - return varToConst[decl]?.ref?.let { cast(it, type) } ?: this - } - return map { it.withConsts(varToConst) } - } + private fun MutableMap, MutableSet>.add(type: RelationType, from: E, to: E) = + getOrPut(from.const.varDecl) { mutableSetOf() }.add(Relation(type, from, to)) - private fun VarDecl.threadVar(pid: Int): VarDecl = - if (xcfa.vars.none { it.wrappedVar == this && !it.threadLocal }) { // if not global var - cast(localVars.getOrPut(this) { mutableMapOf() }.getOrPut(pid) { - Decls.Var("t$pid::$name", type) - }, type) - } else this - - private fun VarDecl.getNewIndexed(increment: Boolean = true): IndexedConstDecl { - val constDecl = getConstDecl(indexing.get(this)) - if (increment) indexing = indexing.inc(this) - return constDecl + private fun Expr.withConsts(varToConst: Map, ConstDecl<*>>): Expr { + if (this is RefExpr) { + return varToConst[decl]?.ref?.let { cast(it, type) } ?: this } + return map { it.withConsts(varToConst) } + } + + private fun VarDecl.threadVar(pid: Int): VarDecl = + if (xcfa.vars.none { it.wrappedVar == this && !it.threadLocal }) { // if not global var + cast( + localVars + .getOrPut(this) { mutableMapOf() } + .getOrPut(pid) { Decls.Var("t$pid::$name", type) }, + type, + ) + } else this + + private fun VarDecl.getNewIndexed(increment: Boolean = true): IndexedConstDecl { + val constDecl = getConstDecl(indexing.get(this)) + if (increment) indexing = indexing.inc(this) + return constDecl + } } diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt index 9469c2eca3..c7027914fc 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli import com.google.common.base.Stopwatch @@ -23,7 +22,7 @@ import hu.bme.mit.theta.analysis.Action import hu.bme.mit.theta.analysis.EmptyCex import hu.bme.mit.theta.analysis.State import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.arg.ARG import hu.bme.mit.theta.analysis.algorithm.arg.debug.ARGWebDebugger @@ -68,318 +67,379 @@ import java.util.concurrent.TimeUnit import kotlin.random.Random fun runConfig( - config: XcfaConfig<*, *>, logger: Logger, uniqueLogger: Logger, - throwDontExit: Boolean + config: XcfaConfig<*, *>, + logger: Logger, + uniqueLogger: Logger, + throwDontExit: Boolean, ): SafetyResult<*, *> { - propagateInputOptions(config, logger, uniqueLogger) + propagateInputOptions(config, logger, uniqueLogger) - registerAllSolverManagers(config.backendConfig.solverHome, logger) + registerAllSolverManagers(config.backendConfig.solverHome, logger) - validateInputOptions(config, logger, uniqueLogger) + validateInputOptions(config, logger, uniqueLogger) - val (xcfa, mcm, parseContext) = frontend(config, logger, uniqueLogger) + val (xcfa, mcm, parseContext) = frontend(config, logger, uniqueLogger) - preVerificationLogging(xcfa, mcm, parseContext, config, logger, uniqueLogger) + preVerificationLogging(xcfa, mcm, parseContext, config, logger, uniqueLogger) - val result = backend(xcfa, mcm, parseContext, config, logger, uniqueLogger, throwDontExit) + val result = backend(xcfa, mcm, parseContext, config, logger, uniqueLogger, throwDontExit) - postVerificationLogging(result, mcm, parseContext, config, logger, uniqueLogger) + postVerificationLogging(result, mcm, parseContext, config, logger, uniqueLogger) - return result + return result } - private fun propagateInputOptions(config: XcfaConfig<*, *>, logger: Logger, uniqueLogger: Logger) { - config.inputConfig.property = determineProperty(config, logger) - LbePass.level = config.frontendConfig.lbeLevel - StaticCoiPass.enabled = config.frontendConfig.staticCoi - if (config.backendConfig.backend == Backend.CEGAR) { - val cegarConfig = config.backendConfig.specConfig - cegarConfig as CegarConfig - val random = Random(cegarConfig.porRandomSeed) - XcfaSporLts.random = random - XcfaDporLts.random = random - } - if (config.debugConfig.argToFile) { - WebDebuggerLogger.enableWebDebuggerLogger() - WebDebuggerLogger.getInstance().setTitle(config.inputConfig.input?.name) - } - - LoopUnrollPass.UNROLL_LIMIT = config.frontendConfig.loopUnroll - LoopUnrollPass.FORCE_UNROLL_LIMIT = config.frontendConfig.forceUnroll - FetchExecuteWriteback.enabled = config.frontendConfig.enableFew - ARGWebDebugger.on = config.debugConfig.argdebug + config.inputConfig.property = determineProperty(config, logger) + LbePass.level = config.frontendConfig.lbeLevel + StaticCoiPass.enabled = config.frontendConfig.staticCoi + if (config.backendConfig.backend == Backend.CEGAR) { + val cegarConfig = config.backendConfig.specConfig + cegarConfig as CegarConfig + val random = Random(cegarConfig.porRandomSeed) + XcfaSporLts.random = random + XcfaDporLts.random = random + } + if (config.debugConfig.argToFile) { + WebDebuggerLogger.enableWebDebuggerLogger() + WebDebuggerLogger.getInstance().setTitle(config.inputConfig.input?.name) + } + + LoopUnrollPass.UNROLL_LIMIT = config.frontendConfig.loopUnroll + LoopUnrollPass.FORCE_UNROLL_LIMIT = config.frontendConfig.forceUnroll + FetchExecuteWriteback.enabled = config.frontendConfig.enableFew + ARGWebDebugger.on = config.debugConfig.argdebug } private fun validateInputOptions(config: XcfaConfig<*, *>, logger: Logger, uniqueLogger: Logger) { - rule("NoCoiWhenDataRace") { - config.backendConfig.backend == Backend.CEGAR && - (config.backendConfig.specConfig as? CegarConfig)?.coi != ConeOfInfluenceMode.NO_COI && - config.inputConfig.property == ErrorDetection.DATA_RACE - } - rule("NoAaporWhenDataRace") { - (config.backendConfig.specConfig as? CegarConfig)?.porLevel?.isAbstractionAware == true && - config.inputConfig.property == ErrorDetection.DATA_RACE - } - rule("DPORWithoutDFS") { - (config.backendConfig.specConfig as? CegarConfig)?.porLevel?.isDynamic == true && - (config.backendConfig.specConfig as? CegarConfig)?.abstractorConfig?.search != Search.DFS - } - rule("SensibleLoopUnrollLimits") { - config.frontendConfig.loopUnroll != -1 && config.frontendConfig.loopUnroll < config.frontendConfig.forceUnroll - } - rule("NoPredSplitUntilFixed(https://github.com/ftsrg/theta/issues/267)") { - (config.backendConfig.specConfig as? CegarConfig)?.abstractorConfig?.domain == Domain.PRED_SPLIT - } + rule("NoCoiWhenDataRace") { + config.backendConfig.backend == Backend.CEGAR && + (config.backendConfig.specConfig as? CegarConfig)?.coi != ConeOfInfluenceMode.NO_COI && + config.inputConfig.property == ErrorDetection.DATA_RACE + } + rule("NoAaporWhenDataRace") { + (config.backendConfig.specConfig as? CegarConfig)?.porLevel?.isAbstractionAware == true && + config.inputConfig.property == ErrorDetection.DATA_RACE + } + rule("DPORWithoutDFS") { + (config.backendConfig.specConfig as? CegarConfig)?.porLevel?.isDynamic == true && + (config.backendConfig.specConfig as? CegarConfig)?.abstractorConfig?.search != Search.DFS + } + rule("SensibleLoopUnrollLimits") { + config.frontendConfig.loopUnroll != -1 && + config.frontendConfig.loopUnroll < config.frontendConfig.forceUnroll + } + rule("NoPredSplitUntilFixed(https://github.com/ftsrg/theta/issues/267)") { + (config.backendConfig.specConfig as? CegarConfig)?.abstractorConfig?.domain == Domain.PRED_SPLIT + } } -fun frontend(config: XcfaConfig<*, *>, logger: Logger, uniqueLogger: Logger): Triple { - if (config.inputConfig.xcfaWCtx != null) { - val xcfa = config.inputConfig.xcfaWCtx!!.first - ConeOfInfluence = if (config.inputConfig.xcfaWCtx!!.third.multiThreading) { - XcfaCoiMultiThread(xcfa) - } else { - XcfaCoiSingleThread(xcfa) - } - return config.inputConfig.xcfaWCtx!! - } - - val stopwatch = Stopwatch.createStarted() - - val input = config.inputConfig.input!! - logger.write(Logger.Level.INFO, "Parsing the input $input as ${config.frontendConfig.inputType}\n") - - val parseContext = ParseContext() - - if (config.frontendConfig.inputType == InputType.C) { - val cConfig = config.frontendConfig.specConfig - cConfig as CFrontendConfig - parseContext.arithmetic = cConfig.arithmetic - parseContext.architecture = cConfig.architecture - } - - val xcfa = getXcfa(config, parseContext, logger, uniqueLogger) - - val mcm = if (config.inputConfig.catFile != null) { - CatDslManager.createMCM(config.inputConfig.catFile!!) +fun frontend( + config: XcfaConfig<*, *>, + logger: Logger, + uniqueLogger: Logger, +): Triple { + if (config.inputConfig.xcfaWCtx != null) { + val xcfa = config.inputConfig.xcfaWCtx!!.first + ConeOfInfluence = + if (config.inputConfig.xcfaWCtx!!.third.multiThreading) { + XcfaCoiMultiThread(xcfa) + } else { + XcfaCoiSingleThread(xcfa) + } + return config.inputConfig.xcfaWCtx!! + } + + val stopwatch = Stopwatch.createStarted() + + val input = config.inputConfig.input!! + logger.write( + Logger.Level.INFO, + "Parsing the input $input as ${config.frontendConfig.inputType}\n", + ) + + val parseContext = ParseContext() + + if (config.frontendConfig.inputType == InputType.C) { + val cConfig = config.frontendConfig.specConfig + cConfig as CFrontendConfig + parseContext.arithmetic = cConfig.arithmetic + parseContext.architecture = cConfig.architecture + } + + val xcfa = getXcfa(config, parseContext, logger, uniqueLogger) + + val mcm = + if (config.inputConfig.catFile != null) { + CatDslManager.createMCM(config.inputConfig.catFile!!) } else { - emptySet() - } - - ConeOfInfluence = if (parseContext.multiThreading) XcfaCoiMultiThread(xcfa) else XcfaCoiSingleThread(xcfa) - - if (parseContext.multiThreading && (config.backendConfig.specConfig as? CegarConfig)?.let { it.abstractorConfig.search == Search.ERR } == true) { - val cConfig = config.backendConfig.specConfig as CegarConfig - cConfig.abstractorConfig.search = Search.DFS - uniqueLogger.write(INFO, "Multithreaded program found, using DFS instead of ERR.") + emptySet() } - logger.write( - Logger.Level.INFO, "Frontend finished: ${xcfa.name} (in ${ + ConeOfInfluence = + if (parseContext.multiThreading) XcfaCoiMultiThread(xcfa) else XcfaCoiSingleThread(xcfa) + + if ( + parseContext.multiThreading && + (config.backendConfig.specConfig as? CegarConfig)?.let { + it.abstractorConfig.search == Search.ERR + } == true + ) { + val cConfig = config.backendConfig.specConfig as CegarConfig + cConfig.abstractorConfig.search = Search.DFS + uniqueLogger.write(INFO, "Multithreaded program found, using DFS instead of ERR.") + } + + logger.write( + Logger.Level.INFO, + "Frontend finished: ${xcfa.name} (in ${ stopwatch.elapsed(TimeUnit.MILLISECONDS) - } ms)\n" - ) + } ms)\n", + ) - logger.write(RESULT, "ParsingResult Success\n") - logger.write(RESULT, - "Alias graph size: ${xcfa.pointsToGraph.size} -> ${xcfa.pointsToGraph.values.map { it.size }.toList()}\n") + logger.write(RESULT, "ParsingResult Success\n") + logger.write( + RESULT, + "Alias graph size: ${xcfa.pointsToGraph.size} -> ${xcfa.pointsToGraph.values.map { it.size }.toList()}\n", + ) - return Triple(xcfa, mcm, parseContext) + return Triple(xcfa, mcm, parseContext) } private fun backend( - xcfa: XCFA, mcm: MCM, parseContext: ParseContext, config: XcfaConfig<*, *>, - logger: Logger, - uniqueLogger: Logger, - throwDontExit: Boolean + xcfa: XCFA, + mcm: MCM, + parseContext: ParseContext, + config: XcfaConfig<*, *>, + logger: Logger, + uniqueLogger: Logger, + throwDontExit: Boolean, ): SafetyResult<*, *> = - if (config.backendConfig.backend == Backend.NONE) { - SafetyResult.unknown() + if (config.backendConfig.backend == Backend.NONE) { + SafetyResult.unknown() + } else { + if ( + xcfa.procedures.all { + it.errorLoc.isEmpty && config.inputConfig.property == ErrorDetection.ERROR_LOCATION + } + ) { + val result = SafetyResult.safe(EmptyProof.getInstance()) + logger.write(Logger.Level.INFO, "Input is trivially safe\n") + + logger.write(RESULT, result.toString() + "\n") + result } else { - if (xcfa.procedures.all { it.errorLoc.isEmpty && config.inputConfig.property == ErrorDetection.ERROR_LOCATION }) { - val result = SafetyResult.safe(EmptyWitness.getInstance()) - logger.write(Logger.Level.INFO, "Input is trivially safe\n") - - logger.write(RESULT, result.toString() + "\n") - result - } else { - val stopwatch = Stopwatch.createStarted() - - logger.write( - Logger.Level.INFO, - "Starting verification of ${if (xcfa.name == "") "UnnamedXcfa" else xcfa.name} using ${config.backendConfig.backend}\n" - ) - - val checker = getChecker(xcfa, mcm, config, parseContext, logger, uniqueLogger) - val result = exitOnError(config.debugConfig.stacktrace, config.debugConfig.debug || throwDontExit) { - checker.check() - }.let { result -> - when { - result.isSafe && LoopUnrollPass.FORCE_UNROLL_USED -> { // cannot report safe if force unroll was used - logger.write(RESULT, "Incomplete loop unroll used: safe result is unreliable.\n") - SafetyResult.unknown() - } - - else -> result - } + val stopwatch = Stopwatch.createStarted() + + logger.write( + Logger.Level.INFO, + "Starting verification of ${if (xcfa.name == "") "UnnamedXcfa" else xcfa.name} using ${config.backendConfig.backend}\n", + ) + + val checker = getChecker(xcfa, mcm, config, parseContext, logger, uniqueLogger) + val result = + exitOnError(config.debugConfig.stacktrace, config.debugConfig.debug || throwDontExit) { + checker.check() + } + .let { result -> + when { + result.isSafe && + LoopUnrollPass.FORCE_UNROLL_USED -> { // cannot report safe if force unroll was used + logger.write(RESULT, "Incomplete loop unroll used: safe result is unreliable.\n") + SafetyResult.unknown() + } + + else -> result } + } - logger.write( - Logger.Level.INFO, "Backend finished (in ${ + logger.write( + Logger.Level.INFO, + "Backend finished (in ${ stopwatch.elapsed(TimeUnit.MILLISECONDS) - } ms)\n" - ) + } ms)\n", + ) - logger.write(RESULT, result.toString() + "\n") - result - } + logger.write(RESULT, result.toString() + "\n") + result } + } private fun preVerificationLogging( - xcfa: XCFA, mcm: MCM, parseContext: ParseContext, config: XcfaConfig<*, *>, - logger: Logger, uniqueLogger: Logger + xcfa: XCFA, + mcm: MCM, + parseContext: ParseContext, + config: XcfaConfig<*, *>, + logger: Logger, + uniqueLogger: Logger, ) { - if (config.outputConfig.enableOutput) { - try { - val resultFolder = config.outputConfig.resultFolder - resultFolder.mkdirs() - - logger.write( - Logger.Level.INFO, - "Writing pre-verification artifacts to directory ${resultFolder.absolutePath}\n" - ) - - if (!config.outputConfig.chcOutputConfig.disable) { - xcfa.procedures.forEach { - try { - val chcFile = File(resultFolder, "xcfa-${it.name}.smt2") - chcFile.writeText(it.toSMT2CHC()) - } catch (e: Exception) { - logger.write(INFO, "Could not write CHC file: " + e.stackTraceToString()) - } - } - } + if (config.outputConfig.enableOutput) { + try { + val resultFolder = config.outputConfig.resultFolder + resultFolder.mkdirs() + + logger.write( + Logger.Level.INFO, + "Writing pre-verification artifacts to directory ${resultFolder.absolutePath}\n", + ) + + if (!config.outputConfig.chcOutputConfig.disable) { + xcfa.procedures.forEach { + try { + val chcFile = File(resultFolder, "xcfa-${it.name}.smt2") + chcFile.writeText(it.toSMT2CHC()) + } catch (e: Exception) { + logger.write(INFO, "Could not write CHC file: " + e.stackTraceToString()) + } + } + } - if (!config.outputConfig.xcfaOutputConfig.disable) { - val xcfaDotFile = File(resultFolder, "xcfa.dot") - xcfaDotFile.writeText(xcfa.toDot()) + if (!config.outputConfig.xcfaOutputConfig.disable) { + val xcfaDotFile = File(resultFolder, "xcfa.dot") + xcfaDotFile.writeText(xcfa.toDot()) - val xcfaJsonFile = File(resultFolder, "xcfa.json") - val uglyJson = getGson(xcfa).toJson(xcfa) - val create = GsonBuilder().setPrettyPrinting().create() - xcfaJsonFile.writeText(create.toJson(JsonParser.parseString(uglyJson))) - } + val xcfaJsonFile = File(resultFolder, "xcfa.json") + val uglyJson = getGson(xcfa).toJson(xcfa) + val create = GsonBuilder().setPrettyPrinting().create() + xcfaJsonFile.writeText(create.toJson(JsonParser.parseString(uglyJson))) + } - if (!config.outputConfig.cOutputConfig.disable) { - try { - val xcfaCFile = File(resultFolder, "xcfa.c") - xcfaCFile.writeText( - xcfa.toC( - parseContext, config.outputConfig.cOutputConfig.useArr, - config.outputConfig.cOutputConfig.useExArr, config.outputConfig.cOutputConfig.useRange - ) - ) - } catch (e: Throwable) { - logger.write(Logger.Level.VERBOSE, "Could not emit C file\n") - } - } + if (!config.outputConfig.cOutputConfig.disable) { + try { + val xcfaCFile = File(resultFolder, "xcfa.c") + xcfaCFile.writeText( + xcfa.toC( + parseContext, + config.outputConfig.cOutputConfig.useArr, + config.outputConfig.cOutputConfig.useExArr, + config.outputConfig.cOutputConfig.useRange, + ) + ) } catch (e: Throwable) { - logger.write(Logger.Level.INFO, "Could not output files: ${e.stackTraceToString()}\n") + logger.write(Logger.Level.VERBOSE, "Could not emit C file\n") } + } + } catch (e: Throwable) { + logger.write(Logger.Level.INFO, "Could not output files: ${e.stackTraceToString()}\n") } + } } private fun postVerificationLogging( - safetyResult: SafetyResult<*, *>, mcm: MCM, - parseContext: ParseContext, config: XcfaConfig<*, *>, logger: Logger, uniqueLogger: Logger + safetyResult: SafetyResult<*, *>, + mcm: MCM, + parseContext: ParseContext, + config: XcfaConfig<*, *>, + logger: Logger, + uniqueLogger: Logger, ) { - if (config.outputConfig.enableOutput) { - try { - // we only want to log the files if the current configuration is not --in-process or portfolio - if (config.backendConfig.inProcess || config.backendConfig.backend == Backend.PORTFOLIO) { - return - } - - val resultFolder = config.outputConfig.resultFolder - resultFolder.mkdirs() - - logger.write( - Logger.Level.INFO, - "Writing post-verification artifacts to directory ${resultFolder.absolutePath}\n" + if (config.outputConfig.enableOutput) { + try { + // we only want to log the files if the current configuration is not --in-process or portfolio + if (config.backendConfig.inProcess || config.backendConfig.backend == Backend.PORTFOLIO) { + return + } + + val resultFolder = config.outputConfig.resultFolder + resultFolder.mkdirs() + + logger.write( + Logger.Level.INFO, + "Writing post-verification artifacts to directory ${resultFolder.absolutePath}\n", + ) + + // TODO eliminate the need for the instanceof check + if ( + !config.outputConfig.argConfig.disable && safetyResult.proof is ARG? + ) { + val argFile = File(resultFolder, "arg-${safetyResult.isSafe}.dot") + val g: Graph = + ArgVisualizer.getDefault().visualize(safetyResult.proof as ARG?) + argFile.writeText(GraphvizWriter.getInstance().writeString(g)) + } + + if (!config.outputConfig.witnessConfig.disable) { + if ( + safetyResult.isUnsafe && + safetyResult.asUnsafe().cex != null && + !config.outputConfig.witnessConfig.svcomp + ) { + val concrTrace: Trace, XcfaAction> = + XcfaTraceConcretizer.concretize( + safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, + getSolver( + config.outputConfig.witnessConfig.concretizerSolver, + config.outputConfig.witnessConfig.validateConcretizerSolver, + ), + parseContext, ) - // TODO eliminate the need for the instanceof check - if (!config.outputConfig.argConfig.disable && safetyResult.witness is ARG?) { - val argFile = File(resultFolder, "arg-${safetyResult.isSafe}.dot") - val g: Graph = ArgVisualizer.getDefault().visualize(safetyResult.witness as ARG?) - argFile.writeText(GraphvizWriter.getInstance().writeString(g)) - } - - if (!config.outputConfig.witnessConfig.disable) { - if (safetyResult.isUnsafe && safetyResult.asUnsafe().cex != null && !config.outputConfig.witnessConfig.svcomp) { - val concrTrace: Trace, XcfaAction> = XcfaTraceConcretizer.concretize( - safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, - getSolver( - config.outputConfig.witnessConfig.concretizerSolver, - config.outputConfig.witnessConfig.validateConcretizerSolver - ), - parseContext - ) - - val traceFile = File(resultFolder, "trace.dot") - val traceG: Graph = TraceVisualizer.getDefault().visualize(concrTrace) - traceFile.writeText(GraphvizWriter.getInstance().writeString(traceG)) - - val sequenceFile = File(resultFolder, "trace.plantuml") - writeSequenceTrace(sequenceFile, - safetyResult.asUnsafe().cex as Trace, XcfaAction>) { (_, act) -> - act.label.getFlatLabels().map(XcfaLabel::toString) - } - - val optSequenceFile = File(resultFolder, "trace-optimized.plantuml") - writeSequenceTrace(optSequenceFile, concrTrace) { (_, act) -> - act.label.getFlatLabels().map(XcfaLabel::toString) - } - - val cSequenceFile = File(resultFolder, "trace-c.plantuml") - writeSequenceTrace(cSequenceFile, concrTrace) { (state, act) -> - val proc = state.processes[act.pid] - val loc = proc?.locs?.peek() - (loc?.metadata as? CMetaData)?.sourceText?.split("\n") ?: listOf("") - } - } - val witnessFile = File(resultFolder, "witness.graphml") - XcfaWitnessWriter().writeWitness( - safetyResult, config.inputConfig.input!!, - getSolver( - config.outputConfig.witnessConfig.concretizerSolver, - config.outputConfig.witnessConfig.validateConcretizerSolver - ), parseContext, witnessFile - ) - } - } catch (e: Throwable) { - logger.write(Logger.Level.INFO, "Could not output files: ${e.stackTraceToString()}\n") + val traceFile = File(resultFolder, "trace.dot") + val traceG: Graph = TraceVisualizer.getDefault().visualize(concrTrace) + traceFile.writeText(GraphvizWriter.getInstance().writeString(traceG)) + + val sequenceFile = File(resultFolder, "trace.plantuml") + writeSequenceTrace( + sequenceFile, + safetyResult.asUnsafe().cex as Trace, XcfaAction>, + ) { (_, act) -> + act.label.getFlatLabels().map(XcfaLabel::toString) + } + + val optSequenceFile = File(resultFolder, "trace-optimized.plantuml") + writeSequenceTrace(optSequenceFile, concrTrace) { (_, act) -> + act.label.getFlatLabels().map(XcfaLabel::toString) + } + + val cSequenceFile = File(resultFolder, "trace-c.plantuml") + writeSequenceTrace(cSequenceFile, concrTrace) { (state, act) -> + val proc = state.processes[act.pid] + val loc = proc?.locs?.peek() + (loc?.metadata as? CMetaData)?.sourceText?.split("\n") ?: listOf("") + } } + val witnessFile = File(resultFolder, "witness.graphml") + XcfaWitnessWriter() + .writeWitness( + safetyResult, + config.inputConfig.input!!, + getSolver( + config.outputConfig.witnessConfig.concretizerSolver, + config.outputConfig.witnessConfig.validateConcretizerSolver, + ), + parseContext, + witnessFile, + ) + } + } catch (e: Throwable) { + logger.write(Logger.Level.INFO, "Could not output files: ${e.stackTraceToString()}\n") } + } } -private fun writeSequenceTrace(sequenceFile: File, trace: Trace, XcfaAction>, - printer: (Pair, XcfaAction>) -> List) { - sequenceFile.writeText("@startuml\n") - var maxWidth = 0 - trace.actions.forEachIndexed { i, it -> - val stateBefore = trace.states[i] - sequenceFile.appendText("hnote over ${it.pid}\n") - val labelStrings = printer(Pair(stateBefore, it)) - if (maxWidth < (labelStrings.maxOfOrNull { it.length } ?: 0)) { - maxWidth = labelStrings.maxOfOrNull { it.length } ?: 0 - } - sequenceFile.appendText("${labelStrings.joinToString("\n")}\n") - sequenceFile.appendText("endhnote\n") +private fun writeSequenceTrace( + sequenceFile: File, + trace: Trace, XcfaAction>, + printer: (Pair, XcfaAction>) -> List, +) { + sequenceFile.writeText("@startuml\n") + var maxWidth = 0 + trace.actions.forEachIndexed { i, it -> + val stateBefore = trace.states[i] + sequenceFile.appendText("hnote over ${it.pid}\n") + val labelStrings = printer(Pair(stateBefore, it)) + if (maxWidth < (labelStrings.maxOfOrNull { it.length } ?: 0)) { + maxWidth = labelStrings.maxOfOrNull { it.length } ?: 0 } - trace.actions.map { it.pid }.distinct().reduce { acc, current -> - sequenceFile.appendText("$acc --> $current: \"${" ".repeat(maxWidth)}\"\n") - current + sequenceFile.appendText("${labelStrings.joinToString("\n")}\n") + sequenceFile.appendText("endhnote\n") + } + trace.actions + .map { it.pid } + .distinct() + .reduce { acc, current -> + sequenceFile.appendText("$acc --> $current: \"${" ".repeat(maxWidth)}\"\n") + current } - sequenceFile.appendText("@enduml\n") -} \ No newline at end of file + sequenceFile.appendText("@enduml\n") +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToBoundedChecker.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToBoundedChecker.kt index 18e0bd82ca..5825b0d922 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToBoundedChecker.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToBoundedChecker.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.checkers import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.bounded.BoundedChecker import hu.bme.mit.theta.analysis.ptr.PtrState @@ -30,35 +29,41 @@ import hu.bme.mit.theta.xcfa.cli.params.XcfaConfig import hu.bme.mit.theta.xcfa.cli.utils.getSolver import hu.bme.mit.theta.xcfa.model.XCFA -fun getBoundedChecker(xcfa: XCFA, mcm: MCM, - config: XcfaConfig<*, *>, - logger: Logger): SafetyChecker>, XcfaAction>, XcfaPrec<*>> { - - val boundedConfig = config.backendConfig.specConfig as BoundedConfig +fun getBoundedChecker( + xcfa: XCFA, + mcm: MCM, + config: XcfaConfig<*, *>, + logger: Logger, +): SafetyChecker>, XcfaAction>, XcfaPrec<*>> { - return BoundedChecker( - monolithicExpr = xcfa.toMonolithicExpr(), - bmcSolver = tryGetSolver(boundedConfig.bmcConfig.bmcSolver, - boundedConfig.bmcConfig.validateBMCSolver)?.createSolver(), - bmcEnabled = { !boundedConfig.bmcConfig.disable }, - lfPathOnly = { !boundedConfig.bmcConfig.nonLfPath }, - itpSolver = tryGetSolver(boundedConfig.itpConfig.itpSolver, - boundedConfig.itpConfig.validateItpSolver)?.createItpSolver(), - imcEnabled = { !boundedConfig.itpConfig.disable }, - indSolver = tryGetSolver(boundedConfig.indConfig.indSolver, - boundedConfig.indConfig.validateIndSolver)?.createSolver(), - kindEnabled = { !boundedConfig.indConfig.disable }, - valToState = { xcfa.valToState(it) }, - biValToAction = { val1, val2 -> xcfa.valToAction(val1, val2) }, - logger = logger - ) as SafetyChecker>, XcfaAction>, XcfaPrec<*>> + val boundedConfig = config.backendConfig.specConfig as BoundedConfig + return BoundedChecker( + monolithicExpr = xcfa.toMonolithicExpr(), + bmcSolver = + tryGetSolver(boundedConfig.bmcConfig.bmcSolver, boundedConfig.bmcConfig.validateBMCSolver) + ?.createSolver(), + bmcEnabled = { !boundedConfig.bmcConfig.disable }, + lfPathOnly = { !boundedConfig.bmcConfig.nonLfPath }, + itpSolver = + tryGetSolver(boundedConfig.itpConfig.itpSolver, boundedConfig.itpConfig.validateItpSolver) + ?.createItpSolver(), + imcEnabled = { !boundedConfig.itpConfig.disable }, + indSolver = + tryGetSolver(boundedConfig.indConfig.indSolver, boundedConfig.indConfig.validateIndSolver) + ?.createSolver(), + kindEnabled = { !boundedConfig.indConfig.disable }, + valToState = { xcfa.valToState(it) }, + biValToAction = { val1, val2 -> xcfa.valToAction(val1, val2) }, + logger = logger, + ) + as SafetyChecker>, XcfaAction>, XcfaPrec<*>> } private fun tryGetSolver(name: String, validate: Boolean): SolverFactory? { - try { - return getSolver(name, validate) - } catch (e: Throwable) { - return null - } -} \ No newline at end of file + try { + return getSolver(name, validate) + } catch (e: Throwable) { + return null + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt index f8bf86f8d2..25a81fdb2e 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToCegarChecker.kt @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.checkers import hu.bme.mit.theta.analysis.PartialOrd import hu.bme.mit.theta.analysis.Prec import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.arg.ARG +import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode import hu.bme.mit.theta.analysis.algorithm.cegar.ArgAbstractor import hu.bme.mit.theta.analysis.algorithm.cegar.ArgCegarChecker import hu.bme.mit.theta.analysis.algorithm.cegar.ArgRefiner @@ -44,109 +43,138 @@ import hu.bme.mit.theta.xcfa.cli.utils.getSolver import hu.bme.mit.theta.xcfa.model.XCFA fun getCegarChecker( - xcfa: XCFA, mcm: MCM, - config: XcfaConfig<*, *>, - logger: Logger -): SafetyChecker, XcfaAction>, Trace>, XcfaAction>, XcfaPrec<*>> { - val cegarConfig = config.backendConfig.specConfig as CegarConfig - val abstractionSolverFactory: SolverFactory = getSolver( - cegarConfig.abstractorConfig.abstractionSolver, - cegarConfig.abstractorConfig.validateAbstractionSolver + xcfa: XCFA, + mcm: MCM, + config: XcfaConfig<*, *>, + logger: Logger, +): SafetyChecker< + ARG, XcfaAction>, + Trace>, XcfaAction>, + XcfaPrec<*>, +> { + val cegarConfig = config.backendConfig.specConfig as CegarConfig + val abstractionSolverFactory: SolverFactory = + getSolver( + cegarConfig.abstractorConfig.abstractionSolver, + cegarConfig.abstractorConfig.validateAbstractionSolver, ) - val refinementSolverFactory: SolverFactory = getSolver( - cegarConfig.refinerConfig.refinementSolver, - cegarConfig.refinerConfig.validateRefinementSolver + val refinementSolverFactory: SolverFactory = + getSolver( + cegarConfig.refinerConfig.refinementSolver, + cegarConfig.refinerConfig.validateRefinementSolver, ) - val ignoredVarRegistry = mutableMapOf, MutableSet>() + val ignoredVarRegistry = mutableMapOf, MutableSet>() - val lts = cegarConfig.coi.getLts(xcfa, ignoredVarRegistry, cegarConfig.porLevel) - val waitlist = if (cegarConfig.porLevel.isDynamic) { - (cegarConfig.coi.porLts as XcfaDporLts).waitlist + val lts = cegarConfig.coi.getLts(xcfa, ignoredVarRegistry, cegarConfig.porLevel) + val waitlist = + if (cegarConfig.porLevel.isDynamic) { + (cegarConfig.coi.porLts as XcfaDporLts).waitlist } else { - PriorityWaitlist.create>, XcfaAction>>( - cegarConfig.abstractorConfig.search.getComp(xcfa) - ) + PriorityWaitlist.create>, XcfaAction>>( + cegarConfig.abstractorConfig.search.getComp(xcfa) + ) } - val abstractionSolverInstance = abstractionSolverFactory.createSolver() - val globalStatePartialOrd: PartialOrd> = cegarConfig.abstractorConfig.domain.partialOrd( - abstractionSolverInstance - ) as PartialOrd> - val corePartialOrd: PartialOrd>> = - if (xcfa.isInlined) getPartialOrder(globalStatePartialOrd) - else getStackPartialOrder(globalStatePartialOrd) - val abstractor: ArgAbstractor = cegarConfig.abstractorConfig.domain.abstractor( - xcfa, - abstractionSolverInstance, - cegarConfig.abstractorConfig.maxEnum, - waitlist, - cegarConfig.refinerConfig.refinement.stopCriterion, - logger, - lts, - config.inputConfig.property, - if (cegarConfig.porLevel.isDynamic) { - XcfaDporLts.getPartialOrder(corePartialOrd) - } else { - corePartialOrd - }, - cegarConfig.abstractorConfig.havocMemory + val abstractionSolverInstance = abstractionSolverFactory.createSolver() + val globalStatePartialOrd: PartialOrd> = + cegarConfig.abstractorConfig.domain.partialOrd(abstractionSolverInstance) + as PartialOrd> + val corePartialOrd: PartialOrd>> = + if (xcfa.isInlined) getPartialOrder(globalStatePartialOrd) + else getStackPartialOrder(globalStatePartialOrd) + val abstractor: ArgAbstractor = + cegarConfig.abstractorConfig.domain.abstractor( + xcfa, + abstractionSolverInstance, + cegarConfig.abstractorConfig.maxEnum, + waitlist, + cegarConfig.refinerConfig.refinement.stopCriterion, + logger, + lts, + config.inputConfig.property, + if (cegarConfig.porLevel.isDynamic) { + XcfaDporLts.getPartialOrder(corePartialOrd) + } else { + corePartialOrd + }, + cegarConfig.abstractorConfig.havocMemory, ) as ArgAbstractor - val ref: ExprTraceChecker = - cegarConfig.refinerConfig.refinement.refiner(refinementSolverFactory, cegarConfig.cexMonitor) - as ExprTraceChecker - val precRefiner: PrecRefiner = - cegarConfig.abstractorConfig.domain.itpPrecRefiner(cegarConfig.refinerConfig.exprSplitter.exprSplitter) - as PrecRefiner - val atomicNodePruner: NodePruner = - cegarConfig.abstractorConfig.domain.nodePruner as NodePruner - val refiner: ArgRefiner = - if (cegarConfig.refinerConfig.refinement == Refinement.MULTI_SEQ) - if (cegarConfig.porLevel == POR.AASPOR) - MultiExprTraceRefiner.create( - ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger, - atomicNodePruner - ) - else - MultiExprTraceRefiner.create(ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger) - else - if (cegarConfig.porLevel == POR.AASPOR) - XcfaSingleExprTraceRefiner.create( - ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger, - atomicNodePruner - ) - else - XcfaSingleExprTraceRefiner.create(ref, precRefiner, cegarConfig.refinerConfig.pruneStrategy, logger) - - val cegarChecker = if (cegarConfig.porLevel == POR.AASPOR) - ArgCegarChecker.create( - abstractor, - AasporRefiner.create(refiner, cegarConfig.refinerConfig.pruneStrategy, ignoredVarRegistry), - logger + val ref: ExprTraceChecker = + cegarConfig.refinerConfig.refinement.refiner(refinementSolverFactory, cegarConfig.cexMonitor) + as ExprTraceChecker + val precRefiner: PrecRefiner = + cegarConfig.abstractorConfig.domain.itpPrecRefiner( + cegarConfig.refinerConfig.exprSplitter.exprSplitter + ) as PrecRefiner + val atomicNodePruner: NodePruner = + cegarConfig.abstractorConfig.domain.nodePruner as NodePruner + val refiner: ArgRefiner = + if (cegarConfig.refinerConfig.refinement == Refinement.MULTI_SEQ) + if (cegarConfig.porLevel == POR.AASPOR) + MultiExprTraceRefiner.create( + ref, + precRefiner, + cegarConfig.refinerConfig.pruneStrategy, + logger, + atomicNodePruner, + ) + else + MultiExprTraceRefiner.create( + ref, + precRefiner, + cegarConfig.refinerConfig.pruneStrategy, + logger, ) + else if (cegarConfig.porLevel == POR.AASPOR) + XcfaSingleExprTraceRefiner.create( + ref, + precRefiner, + cegarConfig.refinerConfig.pruneStrategy, + logger, + atomicNodePruner, + ) else - ArgCegarChecker.create(abstractor, refiner, logger) + XcfaSingleExprTraceRefiner.create( + ref, + precRefiner, + cegarConfig.refinerConfig.pruneStrategy, + logger, + ) - // initialize monitors - MonitorCheckpoint.reset() - if (cegarConfig.cexMonitor == CexMonitorOptions.CHECK) { - val cm = CexMonitor(logger, cegarChecker.witness) - MonitorCheckpoint.register(cm, "CegarChecker.unsafeARG") - } + val cegarChecker = + if (cegarConfig.porLevel == POR.AASPOR) + ArgCegarChecker.create( + abstractor, + AasporRefiner.create(refiner, cegarConfig.refinerConfig.pruneStrategy, ignoredVarRegistry), + logger, + ) + else ArgCegarChecker.create(abstractor, refiner, logger) + + // initialize monitors + MonitorCheckpoint.reset() + if (cegarConfig.cexMonitor == CexMonitorOptions.CHECK) { + val cm = CexMonitor(logger, cegarChecker.proof) + MonitorCheckpoint.register(cm, "CegarChecker.unsafeARG") + } - return object : - SafetyChecker, XcfaAction>, Trace>, XcfaAction>, XcfaPrec<*>> { - override fun check( - prec: XcfaPrec<*>? - ): SafetyResult, XcfaAction>, Trace>, XcfaAction>> { - return cegarChecker.check( - prec - ) as SafetyResult, XcfaAction>, Trace>, XcfaAction>> - } + return object : + SafetyChecker< + ARG, XcfaAction>, + Trace>, XcfaAction>, + XcfaPrec<*>, + > { + override fun check( + prec: XcfaPrec<*>? + ): SafetyResult, XcfaAction>, Trace>, XcfaAction>> { + return cegarChecker.check(prec) + as SafetyResult, XcfaAction>, Trace>, XcfaAction>> + } - override fun check(): SafetyResult, XcfaAction>, Trace>, XcfaAction>> { - return check(cegarConfig.abstractorConfig.domain.initPrec(xcfa, cegarConfig.initPrec)) - } + override fun check(): + SafetyResult, XcfaAction>, Trace>, XcfaAction>> { + return check(cegarConfig.abstractorConfig.domain.initPrec(xcfa, cegarConfig.initPrec)) } -} \ No newline at end of file + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToHornChecker.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToHornChecker.kt index dd63b5eb48..a944126ace 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToHornChecker.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToHornChecker.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.checkers import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.chc.HornChecker @@ -36,32 +35,37 @@ import hu.bme.mit.theta.xcfa.model.XCFA import hu.bme.mit.theta.xcfa2chc.toCHC import org.abego.treelayout.internal.util.Contract.checkState -fun getHornChecker(xcfa: XCFA, mcm: MCM, config: XcfaConfig<*, *>, logger: Logger): - SafetyChecker>, XcfaAction>, XcfaPrec<*>> { +fun getHornChecker( + xcfa: XCFA, + mcm: MCM, + config: XcfaConfig<*, *>, + logger: Logger, +): SafetyChecker>, XcfaAction>, XcfaPrec<*>> { - checkState(xcfa.isInlined, "Only inlined XCFAs work right now") - checkState(xcfa.initProcedures.size == 1, "Only one-procedure XCFAs work right now") + checkState(xcfa.isInlined, "Only inlined XCFAs work right now") + checkState(xcfa.initProcedures.size == 1, "Only one-procedure XCFAs work right now") - val hornConfig = config.backendConfig.specConfig as HornConfig + val hornConfig = config.backendConfig.specConfig as HornConfig - val checker = HornChecker( - relations = xcfa.initProcedures[0].first.toCHC(), - hornSolverFactory = getSolver(hornConfig.solver, hornConfig.validateSolver), - logger = logger, + val checker = + HornChecker( + relations = xcfa.initProcedures[0].first.toCHC(), + hornSolverFactory = getSolver(hornConfig.solver, hornConfig.validateSolver), + logger = logger, ) - return SafetyChecker>, XcfaAction>, XcfaPrec<*>> { - val result = checker.check(null) + return SafetyChecker>, XcfaAction>, XcfaPrec<*>> { + val result = checker.check(null) - if (result.isSafe) { - SafetyResult.safe(EmptyWitness.getInstance()) - } else if (result.isUnsafe) { - val proof = result.asUnsafe().cex - val state = XcfaState>(xcfa, mapOf(), PtrState(PredState.of(proof.proofNode.expr))) - SafetyResult.unsafe(Trace.of(listOf(state), listOf()), EmptyWitness.getInstance()) - } else { - SafetyResult.unknown() - } + if (result.isSafe) { + SafetyResult.safe(EmptyProof.getInstance()) + } else if (result.isUnsafe) { + val proof = result.asUnsafe().cex + val state = + XcfaState>(xcfa, mapOf(), PtrState(PredState.of(proof.proofNode.expr))) + SafetyResult.unsafe(Trace.of(listOf(state), listOf()), EmptyProof.getInstance()) + } else { + SafetyResult.unknown() } - -} \ No newline at end of file + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToOcChecker.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToOcChecker.kt index df14f6ee8f..d8e3fc76ff 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToOcChecker.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/ConfigToOcChecker.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.checkers import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.ptr.PtrState @@ -31,14 +30,21 @@ import hu.bme.mit.theta.xcfa.cli.params.OcConfig import hu.bme.mit.theta.xcfa.cli.params.XcfaConfig import hu.bme.mit.theta.xcfa.model.XCFA -fun getOcChecker(xcfa: XCFA, mcm: MCM, - config: XcfaConfig<*, *>, - logger: Logger): SafetyChecker>, XcfaAction>, XcfaPrec<*>> { - val ocChecker = XcfaOcChecker(xcfa, (config.backendConfig.specConfig as OcConfig).decisionProcedure, logger) - return object : SafetyChecker>, XcfaAction>, XcfaPrec<*>> { - override fun check( - prec: XcfaPrec<*>?): SafetyResult>, XcfaAction>> = check() +fun getOcChecker( + xcfa: XCFA, + mcm: MCM, + config: XcfaConfig<*, *>, + logger: Logger, +): SafetyChecker>, XcfaAction>, XcfaPrec<*>> { + val ocChecker = + XcfaOcChecker(xcfa, (config.backendConfig.specConfig as OcConfig).decisionProcedure, logger) + return object : + SafetyChecker>, XcfaAction>, XcfaPrec<*>> { + override fun check( + prec: XcfaPrec<*>? + ): SafetyResult>, XcfaAction>> = check() - override fun check(): SafetyResult>, XcfaAction>> = ocChecker.check() - } -} \ No newline at end of file + override fun check(): SafetyResult>, XcfaAction>> = + ocChecker.check() + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/InProcessChecker.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/InProcessChecker.kt index a20d9a5aaf..193a062499 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/InProcessChecker.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/checkers/InProcessChecker.kt @@ -13,17 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.checkers import com.zaxxer.nuprocess.NuAbstractProcessHandler import com.zaxxer.nuprocess.NuProcess import com.zaxxer.nuprocess.NuProcessBuilder import hu.bme.mit.theta.analysis.EmptyCex -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyChecker import hu.bme.mit.theta.analysis.algorithm.SafetyResult -import hu.bme.mit.theta.analysis.ptr.PtrState import hu.bme.mit.theta.common.logging.Logger import hu.bme.mit.theta.frontend.ParseContext import hu.bme.mit.theta.xcfa.analysis.XcfaPrec @@ -40,47 +38,48 @@ import java.util.concurrent.TimeUnit import kotlin.io.path.createTempDirectory class InProcessChecker( - val xcfa: XCFA, - val config: XcfaConfig, - val parseContext: ParseContext, - val logger: Logger, -) : SafetyChecker> { - - override fun check( - prec: XcfaPrec<*>?): SafetyResult { - return check() - } - - override fun check(): SafetyResult { - val tempDir = createTempDirectory(config.outputConfig.resultFolder.toPath()) - - val xcfaJson = CachingFileSerializer.serialize("xcfa.json", xcfa) { getGson(xcfa).toJson(xcfa) } - val parseContextJson = CachingFileSerializer.serialize("parseContext.json", parseContext) { - getGson(xcfa).toJson(parseContext) - } - - val processConfig = config.copy( - inputConfig = config.inputConfig.copy( - input = xcfaJson, - parseCtx = parseContextJson, - ), - frontendConfig = config.frontendConfig.copy( - inputType = InputType.JSON - ), - backendConfig = config.backendConfig.copy(inProcess = false, timeoutMs = 0), - outputConfig = config.outputConfig.copy( - resultFolder = tempDir.toFile(), - cOutputConfig = COutputConfig(disable = true), - xcfaOutputConfig = XcfaOutputConfig(disable = true), - argConfig = config.outputConfig.argConfig.copy(disable = false), // we need the arg to be produced - ) - ) - - val configJson = CachingFileSerializer.serialize("config.json", processConfig) { - getGson(xcfa).toJson(processConfig) - } - - val pb = NuProcessBuilder(listOf( + val xcfa: XCFA, + val config: XcfaConfig, + val parseContext: ParseContext, + val logger: Logger, +) : SafetyChecker> { + + override fun check(prec: XcfaPrec<*>?): SafetyResult { + return check() + } + + override fun check(): SafetyResult { + val tempDir = createTempDirectory(config.outputConfig.resultFolder.toPath()) + + val xcfaJson = CachingFileSerializer.serialize("xcfa.json", xcfa) { getGson(xcfa).toJson(xcfa) } + val parseContextJson = + CachingFileSerializer.serialize("parseContext.json", parseContext) { + getGson(xcfa).toJson(parseContext) + } + + val processConfig = + config.copy( + inputConfig = config.inputConfig.copy(input = xcfaJson, parseCtx = parseContextJson), + frontendConfig = config.frontendConfig.copy(inputType = InputType.JSON), + backendConfig = config.backendConfig.copy(inProcess = false, timeoutMs = 0), + outputConfig = + config.outputConfig.copy( + resultFolder = tempDir.toFile(), + cOutputConfig = COutputConfig(disable = true), + xcfaOutputConfig = XcfaOutputConfig(disable = true), + argConfig = + config.outputConfig.argConfig.copy(disable = false), // we need the arg to be produced + ), + ) + + val configJson = + CachingFileSerializer.serialize("config.json", processConfig) { + getGson(xcfa).toJson(processConfig) + } + + val pb = + NuProcessBuilder( + listOf( ProcessHandle.current().info().command().orElse("java"), "-Xss120m", "-Xmx14210m", @@ -88,91 +87,94 @@ class InProcessChecker( File(XcfaCli::class.java.protectionDomain.codeSource.location.toURI()).absolutePath, XcfaCli::class.qualifiedName, "-c", - configJson.absolutePath - ).filterNotNull()) - val processHandler = ProcessHandler() - pb.setProcessListener(processHandler) - val process: NuProcess = pb.start() - pb.environment().putAll(System.getenv()) - - val retCode = process.waitFor(config.backendConfig.timeoutMs, TimeUnit.MILLISECONDS) - val booleanSafetyResult = - if (retCode == Int.MIN_VALUE) { - if (processHandler.safetyResult == null) { - process.destroy(true) - throw ErrorCodeException(ExitCodes.TIMEOUT.code) - } else { - logger.write(Logger.Level.RESULT, - "Config timed out but started writing result, trying to wait an additional 10%...") - val retCode = process.waitFor(config.backendConfig.timeoutMs / 10, TimeUnit.MILLISECONDS) - if (retCode != 0) { - throw ErrorCodeException(retCode) - } else { - processHandler.safetyResult - } - } - } else if (retCode != 0) { - throw ErrorCodeException(retCode) - } else { - processHandler.safetyResult - } - - tempDir.toFile().listFiles()?.forEach { - it.copyTo(config.outputConfig.resultFolder.resolve(it.name), overwrite = true) + configJson.absolutePath, + ) + .filterNotNull() + ) + val processHandler = ProcessHandler() + pb.setProcessListener(processHandler) + val process: NuProcess = pb.start() + pb.environment().putAll(System.getenv()) + + val retCode = process.waitFor(config.backendConfig.timeoutMs, TimeUnit.MILLISECONDS) + val booleanSafetyResult = + if (retCode == Int.MIN_VALUE) { + if (processHandler.safetyResult == null) { + process.destroy(true) + throw ErrorCodeException(ExitCodes.TIMEOUT.code) + } else { + logger.write( + Logger.Level.RESULT, + "Config timed out but started writing result, trying to wait an additional 10%...", + ) + val retCode = process.waitFor(config.backendConfig.timeoutMs / 10, TimeUnit.MILLISECONDS) + if (retCode != 0) { + throw ErrorCodeException(retCode) + } else { + processHandler.safetyResult + } } - tempDir.toFile().deleteRecursively() - - return booleanSafetyResult as SafetyResult + } else if (retCode != 0) { + throw ErrorCodeException(retCode) + } else { + processHandler.safetyResult + } + + tempDir.toFile().listFiles()?.forEach { + it.copyTo(config.outputConfig.resultFolder.resolve(it.name), overwrite = true) } + tempDir.toFile().deleteRecursively() - private class ProcessHandler : NuAbstractProcessHandler() { - - private val stdout = LinkedList() - private var stdoutRemainder = "" - private val stderr = LinkedList() - private var stderrRemainder = "" - var safetyResult: SafetyResult<*, *>? = null - private set - - override fun onStdout(buffer: ByteBuffer, closed: Boolean) { - if (!closed) { - val bytes = ByteArray(buffer.remaining()) - buffer[bytes] - val str = bytes.decodeToString() - - stdoutRemainder += str - if (stdoutRemainder.contains("SafetyResult Safe")) { - safetyResult = SafetyResult.safe(EmptyWitness.getInstance()) - } - if (stdoutRemainder.contains("SafetyResult Unsafe")) { - safetyResult = SafetyResult.unsafe(EmptyCex.getInstance(), EmptyWitness.getInstance()) - } - - val newLines = stdoutRemainder.split("\n") // if ends with \n, last element will be "" - newLines.subList(0, newLines.size - 1).forEach { - stdout.add(it) - println("server: $it") - } - stdoutRemainder = newLines[newLines.size - 1] - } + return booleanSafetyResult as SafetyResult + } + + private class ProcessHandler : NuAbstractProcessHandler() { + + private val stdout = LinkedList() + private var stdoutRemainder = "" + private val stderr = LinkedList() + private var stderrRemainder = "" + var safetyResult: SafetyResult<*, *>? = null + private set + + override fun onStdout(buffer: ByteBuffer, closed: Boolean) { + if (!closed) { + val bytes = ByteArray(buffer.remaining()) + buffer[bytes] + val str = bytes.decodeToString() + + stdoutRemainder += str + if (stdoutRemainder.contains("SafetyResult Safe")) { + safetyResult = SafetyResult.safe(EmptyProof.getInstance()) + } + if (stdoutRemainder.contains("SafetyResult Unsafe")) { + safetyResult = SafetyResult.unsafe(EmptyCex.getInstance(), EmptyProof.getInstance()) } - override fun onStderr(buffer: ByteBuffer, closed: Boolean) { - if (!closed) { - val bytes = ByteArray(buffer.remaining()) - buffer[bytes] - val str = bytes.decodeToString() - - stderrRemainder += str - - val newLines = stderrRemainder.split("\n") // if ends with \n, last element will be "" - newLines.subList(0, newLines.size - 1).forEach { - stderr.add(it) - err.println("server: $it") - } - stderrRemainder = newLines[newLines.size - 1] - } + val newLines = stdoutRemainder.split("\n") // if ends with \n, last element will be "" + newLines.subList(0, newLines.size - 1).forEach { + stdout.add(it) + println("server: $it") } + stdoutRemainder = newLines[newLines.size - 1] + } } -} \ No newline at end of file + override fun onStderr(buffer: ByteBuffer, closed: Boolean) { + if (!closed) { + val bytes = ByteArray(buffer.remaining()) + buffer[bytes] + val str = bytes.decodeToString() + + stderrRemainder += str + + val newLines = stderrRemainder.split("\n") // if ends with \n, last element will be "" + newLines.subList(0, newLines.size - 1).forEach { + stderr.add(it) + err.println("server: $it") + } + stderrRemainder = newLines[newLines.size - 1] + } + } + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt new file mode 100644 index 0000000000..3d29c73fb0 --- /dev/null +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.xcfa.cli + +import hu.bme.mit.theta.xcfa.cli.XcfaCli.Companion.main +import java.util.stream.Stream +import kotlin.io.path.absolutePathString +import kotlin.io.path.createTempDirectory +import kotlin.io.path.exists +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource + +data class WitnessEdge( + val startlineRange: Pair?, + val endlineRange: Pair?, + val startoffsetRange: Pair?, + val endoffsetRange: Pair?, + val assumption: Regex?, +) + +class XcfaCliProofTest { + companion object { + + @JvmStatic + fun cFiles(): Stream { + return Stream.of( + Arguments.of( + "/c/litmustest/singlethread/witness_test.c", + null, + listOf( + WitnessEdge( + startlineRange = Pair(5, 5), + endlineRange = Pair(5, 5), + startoffsetRange = Pair(100, 130), + endoffsetRange = Pair(100, 130), + assumption = Regex("i *== *-1"), + ) + ), + ), + Arguments.of( + "/c/litmustest/singlethread/witness_test.c", + "--backend BOUNDED", + listOf( + WitnessEdge( + startlineRange = Pair(5, 5), + endlineRange = Pair(5, 5), + startoffsetRange = Pair(100, 130), + endoffsetRange = Pair(100, 130), + assumption = Regex("i *== *-1"), + ) + ), + ), + ) + } + } + + @ParameterizedTest + @MethodSource("cFiles") + fun testCWitness(filePath: String, extraArgs: String?, expectedWitnessEdges: List) { + val temp = createTempDirectory() + val params = + arrayOf( + "--enable-output", + "--input-type", + "C", + "--input", + javaClass.getResource(filePath)!!.path, + *(extraArgs?.split(" ")?.toTypedArray() ?: emptyArray()), + "--stacktrace", + "--output-directory", + temp.absolutePathString(), + "--debug", + ) + main(params) + Assertions.assertTrue(temp.resolve("witness.graphml").exists()) + val witnessContents = temp.resolve("witness.graphml").toFile().readText() + val edges = mutableListOf>() + val edgeMatcher = Regex("(?s)(.*)") + val data = mutableMapOf() + for (dataMatch in dataMatcher.findAll(match.value)) { + val (key, value) = dataMatch.destructured + data.put(key, value) + } + edges.add(data) + println( + "Found edge containing data: ${data.entries.map { "${it.key}: ${it.value}" }.joinToString(", ")}" + ) + } + for (expectedWitnessEdge in expectedWitnessEdges) { + Assertions.assertFalse( + edges.none { edge -> + val startline = + expectedWitnessEdge.startlineRange + ?.let { edge["startline"]?.let { v -> Pair(it, Integer.parseInt(v)) } } + ?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false + val endline = + expectedWitnessEdge.endlineRange + ?.let { edge["endline"]?.let { v -> Pair(it, Integer.parseInt(v)) } } + ?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false + val startoffset = + expectedWitnessEdge.startoffsetRange + ?.let { edge["startoffset"]?.let { v -> Pair(it, Integer.parseInt(v)) } } + ?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false + val endoffset = + expectedWitnessEdge.endoffsetRange + ?.let { edge["endoffset"]?.let { v -> Pair(it, Integer.parseInt(v)) } } + ?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false + val assumption = + expectedWitnessEdge.assumption + ?.let { edge["assumption"]?.let { v -> Pair(it, v) } } + ?.let { it.first.matches(it.second) } ?: false + startline && endline && startoffset && endoffset && assumption + }, + "Expected witness edge not found: $expectedWitnessEdge", + ) + } + temp.toFile().deleteRecursively() + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliWitnessTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliWitnessTest.kt deleted file mode 100644 index bc5657f5ba..0000000000 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliWitnessTest.kt +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2024 Budapest University of Technology and Economics - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package hu.bme.mit.theta.xcfa.cli - -import hu.bme.mit.theta.xcfa.cli.XcfaCli.Companion.main -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource -import java.util.stream.Stream -import kotlin.io.path.absolutePathString -import kotlin.io.path.createTempDirectory -import kotlin.io.path.exists - -data class WitnessEdge( - val startlineRange: Pair?, - val endlineRange: Pair?, - val startoffsetRange: Pair?, - val endoffsetRange: Pair?, - val assumption: Regex?, -) - -class XcfaCliWitnessTest { - companion object { - - @JvmStatic - fun cFiles(): Stream { - return Stream.of( - Arguments.of("/c/litmustest/singlethread/witness_test.c", null, listOf( - WitnessEdge( - startlineRange = Pair(5, 5), - endlineRange = Pair(5, 5), - startoffsetRange = Pair(100, 130), - endoffsetRange = Pair(100, 130), - assumption = Regex("i *== *-1"), - ), - )), - Arguments.of("/c/litmustest/singlethread/witness_test.c", "--backend BOUNDED", listOf( - WitnessEdge( - startlineRange = Pair(5, 5), - endlineRange = Pair(5, 5), - startoffsetRange = Pair(100, 130), - endoffsetRange = Pair(100, 130), - assumption = Regex("i *== *-1"), - ), - )), - ) - } - - } - - @ParameterizedTest - @MethodSource("cFiles") - fun testCWitness(filePath: String, extraArgs: String?, expectedWitnessEdges: List) { - val temp = createTempDirectory() - val params = arrayOf( - "--enable-output", - "--input-type", "C", - "--input", javaClass.getResource(filePath)!!.path, - *(extraArgs?.split(" ")?.toTypedArray() ?: emptyArray()), - "--stacktrace", - "--output-directory", temp.absolutePathString(), - "--debug", - ) - main(params) - Assertions.assertTrue(temp.resolve("witness.graphml").exists()) - val witnessContents = temp.resolve("witness.graphml").toFile().readText() - val edges = mutableListOf>() - val edgeMatcher = Regex("(?s)(.*)") - val data = mutableMapOf() - for (dataMatch in dataMatcher.findAll(match.value)) { - val (key, value) = dataMatch.destructured - data.put(key, value) - } - edges.add(data) - println("Found edge containing data: ${data.entries.map { "${it.key}: ${it.value}" }.joinToString(", ")}") - } - for (expectedWitnessEdge in expectedWitnessEdges) { - Assertions.assertFalse( - edges.none { edge -> - val startline = expectedWitnessEdge.startlineRange?.let { - edge["startline"]?.let { v -> - Pair(it, Integer.parseInt(v)) - } - }?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false - val endline = expectedWitnessEdge.endlineRange?.let { - edge["endline"]?.let { v -> - Pair(it, Integer.parseInt(v)) - } - }?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false - val startoffset = expectedWitnessEdge.startoffsetRange?.let { - edge["startoffset"]?.let { v -> - Pair(it, Integer.parseInt(v)) - } - }?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false - val endoffset = expectedWitnessEdge.endoffsetRange?.let { - edge["endoffset"]?.let { v -> - Pair(it, Integer.parseInt(v)) - } - }?.let { it.first.first <= it.second && it.second <= it.first.second } ?: false - val assumption = expectedWitnessEdge.assumption?.let { - edge["assumption"]?.let { v -> - Pair(it, v) - } - }?.let { it.first.matches(it.second) } ?: false - startline && endline && startoffset && endoffset && assumption - }, - "Expected witness edge not found: $expectedWitnessEdge" - ) - } - temp.toFile().deleteRecursively() - } - - -} diff --git a/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/mdd/XstsMddChecker.java b/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/mdd/XstsMddChecker.java index ae9262e03f..b8ae5f098e 100644 --- a/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/mdd/XstsMddChecker.java +++ b/subprojects/xsts/xsts-analysis/src/main/java/hu/bme/mit/theta/xsts/analysis/mdd/XstsMddChecker.java @@ -15,30 +15,32 @@ */ package hu.bme.mit.theta.xsts.analysis.mdd; +import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Eq; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; +import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not; + import com.google.common.base.Preconditions; -import hu.bme.mit.delta.collections.impl.RecursiveIntObjMapViews; -import hu.bme.mit.delta.java.mdd.*; +import hu.bme.mit.delta.java.mdd.JavaMddFactory; +import hu.bme.mit.delta.java.mdd.MddGraph; +import hu.bme.mit.delta.java.mdd.MddHandle; +import hu.bme.mit.delta.java.mdd.MddVariableOrder; import hu.bme.mit.delta.mdd.MddInterpreter; import hu.bme.mit.delta.mdd.MddVariableDescriptor; -import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; +import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.mdd.MddAnalysisStatistics; import hu.bme.mit.theta.analysis.algorithm.mdd.MddCex; import hu.bme.mit.theta.analysis.algorithm.mdd.MddChecker.IterationStrategy; -import hu.bme.mit.theta.analysis.algorithm.mdd.MddWitness; -import hu.bme.mit.theta.analysis.algorithm.mdd.fixedpoint.*; +import hu.bme.mit.theta.analysis.algorithm.mdd.MddProof; import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.AbstractNextStateDescriptor; +import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeInitializer; +import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeNextStateDescriptor; import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.OrNextStateDescriptor; -import hu.bme.mit.theta.common.logging.Logger; -import hu.bme.mit.theta.common.logging.Logger.Level; -import hu.bme.mit.theta.solver.SolverPool; import hu.bme.mit.theta.analysis.algorithm.mdd.expressionnode.ExprLatticeDefinition; import hu.bme.mit.theta.analysis.algorithm.mdd.expressionnode.MddExpressionTemplate; -import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeInitializer; -import hu.bme.mit.theta.analysis.algorithm.mdd.ansd.impl.MddNodeNextStateDescriptor; -import hu.bme.mit.theta.analysis.utils.MddNodeVisualizer; -import hu.bme.mit.theta.common.visualization.Graph; -import hu.bme.mit.theta.common.visualization.writer.GraphvizWriter; +import hu.bme.mit.theta.analysis.algorithm.mdd.fixedpoint.*; +import hu.bme.mit.theta.common.logging.Logger; +import hu.bme.mit.theta.common.logging.Logger.Level; import hu.bme.mit.theta.core.decl.Decl; import hu.bme.mit.theta.core.stmt.NonDetStmt; import hu.bme.mit.theta.core.stmt.SequenceStmt; @@ -48,17 +50,12 @@ import hu.bme.mit.theta.core.utils.PathUtils; import hu.bme.mit.theta.core.utils.StmtUtils; import hu.bme.mit.theta.core.utils.indexings.VarIndexingFactory; +import hu.bme.mit.theta.solver.SolverPool; import hu.bme.mit.theta.xsts.XSTS; - -import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; -import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Eq; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.And; -import static hu.bme.mit.theta.core.type.booltype.SmartBoolExprs.Not; - -public class XstsMddChecker implements SafetyChecker { +public class XstsMddChecker implements SafetyChecker { private final SolverPool solverPool; private final XSTS xsts; @@ -66,7 +63,8 @@ public class XstsMddChecker implements SafetyChecker { private final Logger logger; private IterationStrategy iterationStrategy; - private XstsMddChecker(XSTS xsts, SolverPool solverPool, Logger logger, IterationStrategy iterationStrategy) { + private XstsMddChecker( + XSTS xsts, SolverPool solverPool, Logger logger, IterationStrategy iterationStrategy) { this.xsts = xsts; this.solverPool = solverPool; this.logger = logger; @@ -77,33 +75,64 @@ public static XstsMddChecker create(XSTS xsts, SolverPool solverPool, Logger log return new XstsMddChecker(xsts, solverPool, logger, IterationStrategy.GSAT); } - public static XstsMddChecker create(XSTS xsts, SolverPool solverPool, Logger logger, IterationStrategy iterationStrategy) { + public static XstsMddChecker create( + XSTS xsts, SolverPool solverPool, Logger logger, IterationStrategy iterationStrategy) { return new XstsMddChecker(xsts, solverPool, logger, iterationStrategy); } @Override - public SafetyResult check(Void input) { - - final MddGraph mddGraph = JavaMddFactory.getDefault().createMddGraph(ExprLatticeDefinition.forExpr()); - - final MddVariableOrder stateOrder = JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); - final MddVariableOrder transOrder = JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); - final MddVariableOrder initOrder = JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); - - final NonDetStmt envTran = NonDetStmt.of(xsts.getEnv().getStmts().stream().flatMap(e -> xsts.getTran().getStmts().stream().map(t -> (Stmt) SequenceStmt.of(List.of(e, t)))).toList()); + public SafetyResult check(Void input) { + + final MddGraph mddGraph = + JavaMddFactory.getDefault().createMddGraph(ExprLatticeDefinition.forExpr()); + + final MddVariableOrder stateOrder = + JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); + final MddVariableOrder transOrder = + JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); + final MddVariableOrder initOrder = + JavaMddFactory.getDefault().createMddVariableOrder(mddGraph); + + final NonDetStmt envTran = + NonDetStmt.of( + xsts.getEnv().getStmts().stream() + .flatMap( + e -> + xsts.getTran().getStmts().stream() + .map( + t -> + (Stmt) + SequenceStmt.of( + List.of( + e, + t)))) + .toList()); final var envTranToExprResult = StmtUtils.toExpr(envTran, VarIndexingFactory.indexing(0)); - final var initToExprResult = StmtUtils.toExpr(xsts.getInit(), VarIndexingFactory.indexing(0)); + final var initToExprResult = + StmtUtils.toExpr(xsts.getInit(), VarIndexingFactory.indexing(0)); for (var v : xsts.getVars()) { final var domainSize = /*v.getType() instanceof BoolType ? 2 :*/ 0; stateOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(0), domainSize)); - transOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(envTranToExprResult.getIndexing().get(v) == 0 ? 1 : envTranToExprResult.getIndexing().get(v)), domainSize)); + transOrder.createOnTop( + MddVariableDescriptor.create( + v.getConstDecl( + envTranToExprResult.getIndexing().get(v) == 0 + ? 1 + : envTranToExprResult.getIndexing().get(v)), + domainSize)); transOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(0), domainSize)); // TODO if indexes are identical, inject v'=v - initOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(initToExprResult.getIndexing().get(v) == 0 ? 1 : initToExprResult.getIndexing().get(v)), domainSize)); + initOrder.createOnTop( + MddVariableDescriptor.create( + v.getConstDecl( + initToExprResult.getIndexing().get(v) == 0 + ? 1 + : initToExprResult.getIndexing().get(v)), + domainSize)); initOrder.createOnTop(MddVariableDescriptor.create(v.getConstDecl(0), domainSize)); } @@ -112,21 +141,30 @@ public SafetyResult check(Void input) { final var initSig = initOrder.getDefaultSetSignature(); final Expr initExpr = PathUtils.unfold(xsts.getInitFormula(), 0); - final MddHandle initNode = stateSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(initExpr, o -> (Decl) o, solverPool)); + final MddHandle initNode = + stateSig.getTopVariableHandle() + .checkInNode(MddExpressionTemplate.of(initExpr, o -> (Decl) o, solverPool)); Preconditions.checkState(initToExprResult.getExprs().size() == 1); - final var initUnfold = PathUtils.unfold(initToExprResult.getExprs().stream().findFirst().get(), 0); + final var initUnfold = + PathUtils.unfold(initToExprResult.getExprs().stream().findFirst().get(), 0); final var initIdentityExprs = new ArrayList>(); for (var v : xsts.getVars()) { if (initToExprResult.getIndexing().get(v) == 0) initIdentityExprs.add(Eq(v.getConstDecl(0).getRef(), v.getConstDecl(1).getRef())); } final var initExprWithIdentity = And(initUnfold, And(initIdentityExprs)); - final MddHandle initTranNode = initSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(initExprWithIdentity, o -> (Decl) o, solverPool)); - final AbstractNextStateDescriptor initNextState = MddNodeNextStateDescriptor.of(initTranNode); + final MddHandle initTranNode = + initSig.getTopVariableHandle() + .checkInNode( + MddExpressionTemplate.of( + initExprWithIdentity, o -> (Decl) o, solverPool)); + final AbstractNextStateDescriptor initNextState = + MddNodeNextStateDescriptor.of(initTranNode); final var rel = new LegacyRelationalProductProvider(stateSig.getVariableOrder()); - final var initResult = rel.compute(initNode, initNextState, stateSig.getTopVariableHandle()); + final var initResult = + rel.compute(initNode, initNextState, stateSig.getTopVariableHandle()); logger.write(Level.INFO, "Created initial node"); @@ -138,13 +176,21 @@ public SafetyResult check(Void input) { final var identityExprs = new ArrayList>(); for (var v : xsts.getVars()) { if (stmtToExpr.getIndexing().get(v) < envTranToExprResult.getIndexing().get(v)) - identityExprs.add(Eq(v.getConstDecl(stmtToExpr.getIndexing().get(v)).getRef(), v.getConstDecl(envTranToExprResult.getIndexing().get(v)).getRef())); + identityExprs.add( + Eq( + v.getConstDecl(stmtToExpr.getIndexing().get(v)).getRef(), + v.getConstDecl(envTranToExprResult.getIndexing().get(v)) + .getRef())); if (envTranToExprResult.getIndexing().get(v) == 0) identityExprs.add(Eq(v.getConstDecl(0).getRef(), v.getConstDecl(1).getRef())); } if (!identityExprs.isEmpty()) stmtUnfold = And(stmtUnfold, And(identityExprs)); - MddHandle transitionNode = transSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(stmtUnfold, o -> (Decl) o, solverPool)); + MddHandle transitionNode = + transSig.getTopVariableHandle() + .checkInNode( + MddExpressionTemplate.of( + stmtUnfold, o -> (Decl) o, solverPool)); descriptors.add(MddNodeNextStateDescriptor.of(transitionNode)); } final AbstractNextStateDescriptor nextStates = OrNextStateDescriptor.create(descriptors); @@ -164,12 +210,20 @@ public SafetyResult check(Void input) { } default -> throw new IllegalStateException("Unexpected value: " + iterationStrategy); } - final MddHandle stateSpace = stateSpaceProvider.compute(MddNodeInitializer.of(initResult), nextStates, stateSig.getTopVariableHandle()); + final MddHandle stateSpace = + stateSpaceProvider.compute( + MddNodeInitializer.of(initResult), + nextStates, + stateSig.getTopVariableHandle()); logger.write(Level.INFO, "Enumerated state-space"); final Expr negatedPropExpr = PathUtils.unfold(Not(xsts.getProp()), 0); - final MddHandle propNode = stateSig.getTopVariableHandle().checkInNode(MddExpressionTemplate.of(negatedPropExpr, o -> (Decl) o, solverPool)); + final MddHandle propNode = + stateSig.getTopVariableHandle() + .checkInNode( + MddExpressionTemplate.of( + negatedPropExpr, o -> (Decl) o, solverPool)); final MddHandle propViolating = (MddHandle) stateSpace.intersection(propNode); @@ -181,16 +235,23 @@ public SafetyResult check(Void input) { final Long stateSpaceSize = MddInterpreter.calculateNonzeroCount(stateSpace); logger.write(Level.DETAIL, "State space size: " + stateSpaceSize); - final MddAnalysisStatistics statistics = new MddAnalysisStatistics(violatingSize, stateSpaceSize, stateSpaceProvider.getHitCount(), stateSpaceProvider.getQueryCount(), stateSpaceProvider.getCacheSize()); + final MddAnalysisStatistics statistics = + new MddAnalysisStatistics( + violatingSize, + stateSpaceSize, + stateSpaceProvider.getHitCount(), + stateSpaceProvider.getQueryCount(), + stateSpaceProvider.getCacheSize()); - final SafetyResult result; + final SafetyResult result; if (violatingSize != 0) { - result = SafetyResult.unsafe(MddCex.of(propViolating), MddWitness.of(stateSpace), statistics); + result = + SafetyResult.unsafe( + MddCex.of(propViolating), MddProof.of(stateSpace), statistics); } else { - result = SafetyResult.safe(MddWitness.of(stateSpace), statistics); + result = SafetyResult.safe(MddProof.of(stateSpace), statistics); } logger.write(Level.RESULT, "%s%n", result); return result; - } } diff --git a/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsMddCheckerTest.java b/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsMddCheckerTest.java index bda3053ed6..4208cdfd6a 100644 --- a/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsMddCheckerTest.java +++ b/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsMddCheckerTest.java @@ -15,10 +15,12 @@ */ package hu.bme.mit.theta.xsts.analysis; +import static org.junit.Assert.assertTrue; + import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.mdd.MddCex; import hu.bme.mit.theta.analysis.algorithm.mdd.MddChecker.IterationStrategy; -import hu.bme.mit.theta.analysis.algorithm.mdd.MddWitness; +import hu.bme.mit.theta.analysis.algorithm.mdd.MddProof; import hu.bme.mit.theta.common.logging.ConsoleLogger; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.solver.SolverPool; @@ -26,99 +28,159 @@ import hu.bme.mit.theta.xsts.XSTS; import hu.bme.mit.theta.xsts.analysis.mdd.XstsMddChecker; import hu.bme.mit.theta.xsts.dsl.XstsDslManager; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - import java.io.FileInputStream; -import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.util.Arrays; import java.util.Collection; -import static org.junit.Assert.assertTrue; - public class XstsMddCheckerTest { public static Collection data() { - return Arrays.asList(new Object[][]{ - -// { "src/test/resources/model/trafficlight.xsts", "src/test/resources/property/green_and_red.prop", true}, - - {"src/test/resources/model/trafficlight_v2.xsts", "src/test/resources/property/green_and_red.prop", true}, - - {"src/test/resources/model/counter5.xsts", "src/test/resources/property/x_between_0_and_5.prop", true}, - - {"src/test/resources/model/counter5.xsts", "src/test/resources/property/x_eq_5.prop", false}, - - {"src/test/resources/model/x_and_y.xsts", "src/test/resources/property/x_geq_y.prop", true}, - - {"src/test/resources/model/x_powers.xsts", "src/test/resources/property/x_even.prop", true}, - -// { "src/test/resources/model/cross_with.xsts", "src/test/resources/property/cross.prop", false}, - -// { "src/test/resources/model/cross_without.xsts", "src/test/resources/property/cross.prop", false}, - - {"src/test/resources/model/choices.xsts", "src/test/resources/property/choices.prop", false}, - -// { "src/test/resources/model/literals.xsts", "src/test/resources/property/literals.prop", true}, - -// { "src/test/resources/model/cross3.xsts", "src/test/resources/property/cross.prop", false}, - - {"src/test/resources/model/sequential.xsts", "src/test/resources/property/sequential.prop", true}, - - {"src/test/resources/model/sequential.xsts", "src/test/resources/property/sequential2.prop", false}, - - {"src/test/resources/model/on_off_statemachine.xsts", "src/test/resources/property/on_off_statemachine.prop", false}, - - {"src/test/resources/model/on_off_statemachine.xsts", "src/test/resources/property/on_off_statemachine2.prop", true}, - - {"src/test/resources/model/on_off_statemachine.xsts", "src/test/resources/property/on_off_statemachine3.prop", false}, - -// {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_5.prop", false}, -// -// {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_50.prop", false}, -// -// {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_51.prop", true}, - - {"src/test/resources/model/count_up_down.xsts", "src/test/resources/property/count_up_down.prop", false}, - - {"src/test/resources/model/count_up_down.xsts", "src/test/resources/property/count_up_down2.prop", true}, - -// {"src/test/resources/model/bhmr2007.xsts", "src/test/resources/property/bhmr2007.prop", true}, -// -// {"src/test/resources/model/css2003.xsts", "src/test/resources/property/css2003.prop", true}, -// -// { "src/test/resources/model/array_counter.xsts", "src/test/resources/property/array_10.prop", false}, -// -// { "src/test/resources/model/array_constant.xsts", "src/test/resources/property/array_constant.prop", true}, -// -// { "src/test/resources/model/localvars.xsts", "src/test/resources/property/localvars.prop", true}, -// -// { "src/test/resources/model/localvars2.xsts", "src/test/resources/property/localvars2.prop", true}, -// -// { "src/test/resources/model/loopxy.xsts", "src/test/resources/property/loopxy.prop", true}, -// -// { "src/test/resources/model/arraywrite_sugar.xsts", "src/test/resources/property/arraywrite_sugar.prop", false}, -// -// { "src/test/resources/model/if1.xsts", "src/test/resources/property/if1.prop", true}, -// -// { "src/test/resources/model/if2.xsts", "src/test/resources/property/if2.prop", false} - }); + return Arrays.asList( + new Object[][] { + + // { "src/test/resources/model/trafficlight.xsts", + // "src/test/resources/property/green_and_red.prop", true}, + + { + "src/test/resources/model/trafficlight_v2.xsts", + "src/test/resources/property/green_and_red.prop", + true + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_between_0_and_5.prop", + true + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_eq_5.prop", + false + }, + { + "src/test/resources/model/x_and_y.xsts", + "src/test/resources/property/x_geq_y.prop", + true + }, + { + "src/test/resources/model/x_powers.xsts", + "src/test/resources/property/x_even.prop", + true + }, + + // { "src/test/resources/model/cross_with.xsts", + // "src/test/resources/property/cross.prop", false}, + + // { "src/test/resources/model/cross_without.xsts", + // "src/test/resources/property/cross.prop", false}, + + { + "src/test/resources/model/choices.xsts", + "src/test/resources/property/choices.prop", + false + }, + + // { "src/test/resources/model/literals.xsts", + // "src/test/resources/property/literals.prop", true}, + + // { "src/test/resources/model/cross3.xsts", + // "src/test/resources/property/cross.prop", false}, + + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential.prop", + true + }, + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential2.prop", + false + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine.prop", + false + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine2.prop", + true + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine3.prop", + false + }, + + // {"src/test/resources/model/counter50.xsts", + // "src/test/resources/property/x_eq_5.prop", false}, + // + // {"src/test/resources/model/counter50.xsts", + // "src/test/resources/property/x_eq_50.prop", false}, + // + // {"src/test/resources/model/counter50.xsts", + // "src/test/resources/property/x_eq_51.prop", true}, + + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down.prop", + false + }, + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down2.prop", + true + }, + + // {"src/test/resources/model/bhmr2007.xsts", + // "src/test/resources/property/bhmr2007.prop", true}, + // + // {"src/test/resources/model/css2003.xsts", + // "src/test/resources/property/css2003.prop", true}, + // + // { "src/test/resources/model/array_counter.xsts", + // "src/test/resources/property/array_10.prop", false}, + // + // { "src/test/resources/model/array_constant.xsts", + // "src/test/resources/property/array_constant.prop", true}, + // + // { "src/test/resources/model/localvars.xsts", + // "src/test/resources/property/localvars.prop", true}, + // + // { "src/test/resources/model/localvars2.xsts", + // "src/test/resources/property/localvars2.prop", true}, + // + // { "src/test/resources/model/loopxy.xsts", + // "src/test/resources/property/loopxy.prop", true}, + // + // { "src/test/resources/model/arraywrite_sugar.xsts", + // "src/test/resources/property/arraywrite_sugar.prop", false}, + // + // { "src/test/resources/model/if1.xsts", + // "src/test/resources/property/if1.prop", true}, + // + // { "src/test/resources/model/if2.xsts", + // "src/test/resources/property/if2.prop", false} + }); } - public static void runTestWithIterationStrategy(String filePath, String propPath, boolean safe, IterationStrategy iterationStrategy) throws Exception { + public static void runTestWithIterationStrategy( + String filePath, String propPath, boolean safe, IterationStrategy iterationStrategy) + throws Exception { final Logger logger = new ConsoleLogger(Logger.Level.SUBSTEP); XSTS xsts; - try (InputStream inputStream = new SequenceInputStream(new FileInputStream(filePath), new FileInputStream(propPath))) { + try (InputStream inputStream = + new SequenceInputStream( + new FileInputStream(filePath), new FileInputStream(propPath))) { xsts = XstsDslManager.createXsts(inputStream); } - final SafetyResult status; + final SafetyResult status; try (var solverPool = new SolverPool(Z3LegacySolverFactory.getInstance())) { - final XstsMddChecker checker = XstsMddChecker.create(xsts, solverPool, logger, iterationStrategy); + final XstsMddChecker checker = + XstsMddChecker.create(xsts, solverPool, logger, iterationStrategy); status = checker.check(null); } @@ -128,5 +190,4 @@ public static void runTestWithIterationStrategy(String filePath, String propPath assertTrue(status.isUnsafe()); } } - } diff --git a/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliBounded.kt b/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliBounded.kt index b0582bf87f..7df23a5d53 100644 --- a/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliBounded.kt +++ b/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliBounded.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xsts.cli import com.github.ajalt.clikt.parameters.options.default @@ -21,7 +20,7 @@ import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.enum import com.google.common.base.Stopwatch import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness +import hu.bme.mit.theta.analysis.algorithm.EmptyProof import hu.bme.mit.theta.analysis.algorithm.SafetyResult import hu.bme.mit.theta.analysis.algorithm.bounded.* import hu.bme.mit.theta.analysis.expl.ExplState @@ -40,84 +39,109 @@ import kotlin.system.exitProcess typealias S = XstsState -class XstsCliBounded : XstsCliBaseCommand( +class XstsCliBounded : + XstsCliBaseCommand( name = "BOUNDED", - help = "Bounded model checking algorithms (BMC, IMC, KINDUCTION). Use --variant to select the algorithm (by default BMC is selected)." -) { - - enum class Variant { - BMC { + help = + "Bounded model checking algorithms (BMC, IMC, KINDUCTION). Use --variant to select the algorithm (by default BMC is selected).", + ) { - override fun buildChecker( - monolithicExpr: MonolithicExpr, solverFactory: SolverFactory, - valToState: (Valuation) -> S, biValToAction: (Valuation, Valuation) -> XstsAction, - logger: Logger - ) = buildBMC(monolithicExpr, solverFactory.createSolver(), valToState, biValToAction, logger) - }, - KINDUCTION { + enum class Variant { + BMC { - override fun buildChecker( - monolithicExpr: MonolithicExpr, solverFactory: SolverFactory, - valToState: (Valuation) -> S, biValToAction: (Valuation, Valuation) -> XstsAction, - logger: Logger - ) = buildKIND( - monolithicExpr, solverFactory.createSolver(), solverFactory.createSolver(), valToState, biValToAction, - logger - ) - }, - IMC { + override fun buildChecker( + monolithicExpr: MonolithicExpr, + solverFactory: SolverFactory, + valToState: (Valuation) -> S, + biValToAction: (Valuation, Valuation) -> XstsAction, + logger: Logger, + ) = buildBMC(monolithicExpr, solverFactory.createSolver(), valToState, biValToAction, logger) + }, + KINDUCTION { - override fun buildChecker( - monolithicExpr: MonolithicExpr, solverFactory: SolverFactory, - valToState: (Valuation) -> S, biValToAction: (Valuation, Valuation) -> XstsAction, - logger: Logger - ) = buildIMC( - monolithicExpr, solverFactory.createSolver(), solverFactory.createItpSolver(), valToState, - biValToAction, logger - ) - }; + override fun buildChecker( + monolithicExpr: MonolithicExpr, + solverFactory: SolverFactory, + valToState: (Valuation) -> S, + biValToAction: (Valuation, Valuation) -> XstsAction, + logger: Logger, + ) = + buildKIND( + monolithicExpr, + solverFactory.createSolver(), + solverFactory.createSolver(), + valToState, + biValToAction, + logger, + ) + }, + IMC { - abstract fun buildChecker( - monolithicExpr: MonolithicExpr, solverFactory: SolverFactory, valToState: (Valuation) -> S, - biValToAction: (Valuation, Valuation) -> XstsAction, logger: Logger - ): BoundedChecker - } + override fun buildChecker( + monolithicExpr: MonolithicExpr, + solverFactory: SolverFactory, + valToState: (Valuation) -> S, + biValToAction: (Valuation, Valuation) -> XstsAction, + logger: Logger, + ) = + buildIMC( + monolithicExpr, + solverFactory.createSolver(), + solverFactory.createItpSolver(), + valToState, + biValToAction, + logger, + ) + }; - private val variant by option().enum().default(Variant.BMC) + abstract fun buildChecker( + monolithicExpr: MonolithicExpr, + solverFactory: SolverFactory, + valToState: (Valuation) -> S, + biValToAction: (Valuation, Valuation) -> XstsAction, + logger: Logger, + ): BoundedChecker + } - private fun printResult(status: SafetyResult>, xsts: XSTS, totalTimeMs: Long) { - if (!outputOptions.benchmarkMode) return - printCommonResult(status, xsts, totalTimeMs) - val stats = status.stats.orElse(BoundedStatistics(0)) as BoundedStatistics - listOf( - stats.iterations, - ).forEach(writer::cell) - writer.newRow() - } + private val variant by option().enum().default(Variant.BMC) - override fun run() { - try { - doRun() - } catch (e: Exception) { - printError(e) - exitProcess(1) - } - } + private fun printResult( + status: SafetyResult>, + xsts: XSTS, + totalTimeMs: Long, + ) { + if (!outputOptions.benchmarkMode) return + printCommonResult(status, xsts, totalTimeMs) + val stats = status.stats.orElse(BoundedStatistics(0)) as BoundedStatistics + listOf(stats.iterations).forEach(writer::cell) + writer.newRow() + } - private fun doRun() { - registerSolverManagers() - val solverFactory = SolverManager.resolveSolverFactory(solver) - val xsts = inputOptions.loadXsts() - val sw = Stopwatch.createStarted() - val checker = variant.buildChecker( - xsts.toMonolithicExpr(), solverFactory, xsts::valToState, - xsts::valToAction, - logger - ) - val result = checker.check() - sw.stop() - printResult(result, xsts, sw.elapsed(TimeUnit.MILLISECONDS)) - writeCex(result, xsts) + override fun run() { + try { + doRun() + } catch (e: Exception) { + printError(e) + exitProcess(1) } + } -} \ No newline at end of file + private fun doRun() { + registerSolverManagers() + val solverFactory = SolverManager.resolveSolverFactory(solver) + val xsts = inputOptions.loadXsts() + val sw = Stopwatch.createStarted() + val checker = + variant.buildChecker( + xsts.toMonolithicExpr(), + solverFactory, + xsts::valToState, + xsts::valToAction, + logger, + ) + val result = checker.check() + sw.stop() + printResult(result, xsts, sw.elapsed(TimeUnit.MILLISECONDS)) + writeCex(result, xsts) + } +} diff --git a/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliCegar.kt b/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliCegar.kt index ee455f86dc..ade34d7127 100644 --- a/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliCegar.kt +++ b/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliCegar.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xsts.cli import com.github.ajalt.clikt.parameters.options.default @@ -38,73 +37,90 @@ import hu.bme.mit.theta.xsts.analysis.config.XstsConfigBuilder.* import java.util.concurrent.TimeUnit import kotlin.system.exitProcess -class XstsCliCegar : XstsCliBaseCommand( +class XstsCliCegar : + XstsCliBaseCommand( name = "CEGAR", - help = "Model checking using the CEGAR (CounterExample Guided Abstraction Refinement) algorithm" -) { + help = "Model checking using the CEGAR (CounterExample Guided Abstraction Refinement) algorithm", + ) { - private val domain: Domain by option(help = "Abstraction domain to use").enum().default(Domain.PRED_CART) - private val refinement: Refinement by option(help = "Refinement strategy to use").enum() - .default(Refinement.SEQ_ITP) - private val search: Search by option(help = "Search strategy to use").enum().default(Search.BFS) - private val refinementSolver: String? by option(help = "Use a different solver for abstraction") - private val abstractionSolver: String? by option(help = "Use a different solver for refinement") - private val predsplit: PredSplit by option().enum().default(PredSplit.WHOLE) - private val maxenum: Int by option().int().default(0) - private val autoexpl: AutoExpl by option().enum().default(AutoExpl.NEWOPERANDS) - private val initprec: InitPrec by option().enum().default(InitPrec.EMPTY) - private val prunestrategy: PruneStrategy by option().enum().default(PruneStrategy.LAZY) - private val optimizestmts: OptimizeStmts by option().enum().default(OptimizeStmts.ON) + private val domain: Domain by + option(help = "Abstraction domain to use").enum().default(Domain.PRED_CART) + private val refinement: Refinement by + option(help = "Refinement strategy to use").enum().default(Refinement.SEQ_ITP) + private val search: Search by + option(help = "Search strategy to use").enum().default(Search.BFS) + private val refinementSolver: String? by option(help = "Use a different solver for abstraction") + private val abstractionSolver: String? by option(help = "Use a different solver for refinement") + private val predsplit: PredSplit by option().enum().default(PredSplit.WHOLE) + private val maxenum: Int by option().int().default(0) + private val autoexpl: AutoExpl by option().enum().default(AutoExpl.NEWOPERANDS) + private val initprec: InitPrec by option().enum().default(InitPrec.EMPTY) + private val prunestrategy: PruneStrategy by + option().enum().default(PruneStrategy.LAZY) + private val optimizestmts: OptimizeStmts by + option().enum().default(OptimizeStmts.ON) - private fun printResult(status: SafetyResult?, out Trace<*, *>?>, xsts: XSTS, totalTimeMs: Long) { - if (!outputOptions.benchmarkMode) return - printCommonResult(status, xsts, totalTimeMs) - val stats = status.stats.orElse(CegarStatistics(0, 0, 0, 0)) as CegarStatistics - listOf( - stats.algorithmTimeMs, - stats.abstractorTimeMs, - stats.refinerTimeMs, - stats.iterations, - status.witness!!.size(), - status.witness!!.depth, - status.witness!!.meanBranchingFactor, - ).forEach(writer::cell) - writer.newRow() - } + private fun printResult( + status: SafetyResult?, out Trace<*, *>?>, + xsts: XSTS, + totalTimeMs: Long, + ) { + if (!outputOptions.benchmarkMode) return + printCommonResult(status, xsts, totalTimeMs) + val stats = status.stats.orElse(CegarStatistics(0, 0, 0, 0)) as CegarStatistics + listOf( + stats.algorithmTimeMs, + stats.abstractorTimeMs, + stats.refinerTimeMs, + stats.iterations, + status.proof!!.size(), + status.proof!!.depth, + status.proof!!.meanBranchingFactor, + ) + .forEach(writer::cell) + writer.newRow() + } - private fun writeVisualStatus( - status: SafetyResult?, out Trace?> - ) { - if (outputOptions.visualize == null) return - val graph = if (status.isSafe) ArgVisualizer.getDefault().visualize(status.asSafe().witness) - else TraceVisualizer.getDefault().visualize(status.asUnsafe().cex) - GraphvizWriter.getInstance().writeFile(graph, outputOptions.visualize!!) - } - - override fun run() { - try { - doRun() - } catch (e: Exception) { - printError(e) - exitProcess(1) - } - } + private fun writeVisualStatus( + status: SafetyResult?, out Trace?> + ) { + if (outputOptions.visualize == null) return + val graph = + if (status.isSafe) ArgVisualizer.getDefault().visualize(status.asSafe().proof) + else TraceVisualizer.getDefault().visualize(status.asUnsafe().cex) + GraphvizWriter.getInstance().writeFile(graph, outputOptions.visualize!!) + } - private fun doRun() { - registerSolverManagers() - val abstractionSolverFactory = SolverManager.resolveSolverFactory(abstractionSolver ?: solver) - val refinementSolverFactory = SolverManager.resolveSolverFactory(refinementSolver ?: solver) - val xsts = inputOptions.loadXsts() - val config = - XstsConfigBuilder(domain, refinement, abstractionSolverFactory, refinementSolverFactory).maxEnum(maxenum) - .autoExpl(autoexpl).initPrec(initprec).pruneStrategy(prunestrategy).search(search).predSplit(predsplit) - .optimizeStmts(optimizestmts).logger(logger).build(xsts) - val sw = Stopwatch.createStarted() - val result = config.check() - sw.stop() - printResult(result, xsts, sw.elapsed(TimeUnit.MILLISECONDS)) - writeCex(result, xsts) - writeVisualStatus(result) + override fun run() { + try { + doRun() + } catch (e: Exception) { + printError(e) + exitProcess(1) } + } -} \ No newline at end of file + private fun doRun() { + registerSolverManagers() + val abstractionSolverFactory = SolverManager.resolveSolverFactory(abstractionSolver ?: solver) + val refinementSolverFactory = SolverManager.resolveSolverFactory(refinementSolver ?: solver) + val xsts = inputOptions.loadXsts() + val config = + XstsConfigBuilder(domain, refinement, abstractionSolverFactory, refinementSolverFactory) + .maxEnum(maxenum) + .autoExpl(autoexpl) + .initPrec(initprec) + .pruneStrategy(prunestrategy) + .search(search) + .predSplit(predsplit) + .optimizeStmts(optimizestmts) + .logger(logger) + .build(xsts) + val sw = Stopwatch.createStarted() + val result = config.check() + sw.stop() + printResult(result, xsts, sw.elapsed(TimeUnit.MILLISECONDS)) + writeCex(result, xsts) + writeVisualStatus(result) + } +} diff --git a/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliMdd.kt b/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliMdd.kt index cc74818770..f64094d0a8 100644 --- a/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliMdd.kt +++ b/subprojects/xsts/xsts-cli/src/main/kotlin/hu/bme/mit/theta/xsts/cli/XstsCliMdd.kt @@ -13,80 +13,70 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xsts.cli import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.option -import com.github.ajalt.clikt.parameters.options.required import com.github.ajalt.clikt.parameters.types.enum import com.google.common.base.Stopwatch -import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.EmptyWitness import hu.bme.mit.theta.analysis.algorithm.SafetyResult -import hu.bme.mit.theta.analysis.algorithm.bounded.* -import hu.bme.mit.theta.analysis.algorithm.cegar.CegarStatistics import hu.bme.mit.theta.analysis.algorithm.mdd.MddAnalysisStatistics import hu.bme.mit.theta.analysis.algorithm.mdd.MddCex import hu.bme.mit.theta.analysis.algorithm.mdd.MddChecker -import hu.bme.mit.theta.analysis.algorithm.mdd.MddWitness -import hu.bme.mit.theta.common.logging.Logger -import hu.bme.mit.theta.core.model.Valuation -import hu.bme.mit.theta.solver.SolverFactory +import hu.bme.mit.theta.analysis.algorithm.mdd.MddProof import hu.bme.mit.theta.solver.SolverManager import hu.bme.mit.theta.solver.SolverPool import hu.bme.mit.theta.xsts.XSTS -import hu.bme.mit.theta.xsts.analysis.XstsAction -import hu.bme.mit.theta.xsts.analysis.hu.bme.mit.theta.xsts.analysis.toMonolithicExpr -import hu.bme.mit.theta.xsts.analysis.hu.bme.mit.theta.xsts.analysis.valToAction -import hu.bme.mit.theta.xsts.analysis.hu.bme.mit.theta.xsts.analysis.valToState import hu.bme.mit.theta.xsts.analysis.mdd.XstsMddChecker import java.util.concurrent.TimeUnit import kotlin.system.exitProcess -class XstsCliMdd : XstsCliBaseCommand( +class XstsCliMdd : + XstsCliBaseCommand( name = "MDD", - help = "Model checking of XSTS using MDDs (Multi-value Decision Diagrams)" -) { - - private val iterationStrategy: MddChecker.IterationStrategy by option( - help = "The state space enumeration algorithm to use" - ).enum().default(MddChecker.IterationStrategy.GSAT) + help = "Model checking of XSTS using MDDs (Multi-value Decision Diagrams)", + ) { - private fun printResult(status: SafetyResult, xsts: XSTS, totalTimeMs: Long) { - if (!outputOptions.benchmarkMode) return - printCommonResult(status, xsts, totalTimeMs) - val stats = status.stats.orElse(MddAnalysisStatistics(0, 0, 0, 0, 0)) as MddAnalysisStatistics - listOf( - stats.violatingSize, - stats.stateSpaceSize, - stats.hitCount, - stats.queryCount, - stats.cacheSize, - ).forEach(writer::cell) - writer.newRow() - } + private val iterationStrategy: MddChecker.IterationStrategy by + option(help = "The state space enumeration algorithm to use") + .enum() + .default(MddChecker.IterationStrategy.GSAT) - override fun run() { - try { - doRun() - } catch (e: Exception) { - printError(e) - exitProcess(1) - } - } + private fun printResult(status: SafetyResult, xsts: XSTS, totalTimeMs: Long) { + if (!outputOptions.benchmarkMode) return + printCommonResult(status, xsts, totalTimeMs) + val stats = status.stats.orElse(MddAnalysisStatistics(0, 0, 0, 0, 0)) as MddAnalysisStatistics + listOf( + stats.violatingSize, + stats.stateSpaceSize, + stats.hitCount, + stats.queryCount, + stats.cacheSize, + ) + .forEach(writer::cell) + writer.newRow() + } - private fun doRun() { - registerSolverManagers() - val solverFactory = SolverManager.resolveSolverFactory(solver) - val xsts = inputOptions.loadXsts() - val sw = Stopwatch.createStarted() - val result = SolverPool(solverFactory).use { - val checker = XstsMddChecker.create(xsts, it, logger, iterationStrategy) - checker.check(null) - } - sw.stop() - printResult(result, xsts, sw.elapsed(TimeUnit.MILLISECONDS)) + override fun run() { + try { + doRun() + } catch (e: Exception) { + printError(e) + exitProcess(1) } + } -} \ No newline at end of file + private fun doRun() { + registerSolverManagers() + val solverFactory = SolverManager.resolveSolverFactory(solver) + val xsts = inputOptions.loadXsts() + val sw = Stopwatch.createStarted() + val result = + SolverPool(solverFactory).use { + val checker = XstsMddChecker.create(xsts, it, logger, iterationStrategy) + checker.check(null) + } + sw.stop() + printResult(result, xsts, sw.elapsed(TimeUnit.MILLISECONDS)) + } +} diff --git a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/LazyXtaCheckerTest.java b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/LazyXtaCheckerTest.java index be1fc4afe0..eefc740ce6 100644 --- a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/LazyXtaCheckerTest.java +++ b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/LazyXtaCheckerTest.java @@ -15,13 +15,17 @@ */ package hu.bme.mit.theta.xta.analysis; +import static hu.bme.mit.theta.analysis.algorithm.arg.SearchStrategy.BFS; +import static hu.bme.mit.theta.xta.analysis.lazy.ClockStrategy.LU; +import static org.junit.Assert.assertTrue; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import hu.bme.mit.theta.analysis.Trace; +import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; import hu.bme.mit.theta.analysis.algorithm.arg.ArgChecker; -import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.unit.UnitPrec; import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory; import hu.bme.mit.theta.xta.XtaSystem; @@ -29,6 +33,10 @@ import hu.bme.mit.theta.xta.analysis.lazy.DataStrategy; import hu.bme.mit.theta.xta.analysis.lazy.LazyXtaCheckerFactory; import hu.bme.mit.theta.xta.dsl.XtaDslManager; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,15 +44,6 @@ import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; - -import static hu.bme.mit.theta.analysis.algorithm.arg.SearchStrategy.BFS; -import static hu.bme.mit.theta.xta.analysis.lazy.ClockStrategy.LU; -import static org.junit.Assert.assertTrue; - @RunWith(Parameterized.class) public final class LazyXtaCheckerTest { @@ -55,13 +54,17 @@ public final class LazyXtaCheckerTest { private static final String MODEL_ENGINE = "/engine-classic.xta"; private static final String MODEL_BROADCAST = "/broadcast.xta"; - private static final Collection MODELS = ImmutableList.of(MODEL_CSMA, MODEL_FDDI, - MODEL_FISCHER, - MODEL_LYNCH, MODEL_ENGINE, MODEL_BROADCAST); + private static final Collection MODELS = + ImmutableList.of( + MODEL_CSMA, + MODEL_FDDI, + MODEL_FISCHER, + MODEL_LYNCH, + MODEL_ENGINE, + MODEL_BROADCAST); - private static final Collection MODELS_WITH_UNKNOWN_SOLVER_STATUS = ImmutableSet.of( - MODEL_FDDI, - MODEL_ENGINE, MODEL_BROADCAST); + private static final Collection MODELS_WITH_UNKNOWN_SOLVER_STATUS = + ImmutableSet.of(MODEL_FDDI, MODEL_ENGINE, MODEL_BROADCAST); @Parameter(0) public String filepath; @@ -72,7 +75,11 @@ public final class LazyXtaCheckerTest { @Parameter(2) public ClockStrategy clockStrategy; - private SafetyChecker, XtaAction>, ? extends Trace, XtaAction>, UnitPrec> checker; + private SafetyChecker< + ? extends ARG, XtaAction>, + ? extends Trace, XtaAction>, + UnitPrec> + checker; @Parameters(name = "model: {0}, discrete: {1}, clock: {2}") public static Collection data() { @@ -80,9 +87,9 @@ public static Collection data() { for (final String model : MODELS) { for (final DataStrategy dataStrategy : DataStrategy.values()) { for (final ClockStrategy clockStrategy : ClockStrategy.values()) { - if (!MODELS_WITH_UNKNOWN_SOLVER_STATUS.contains(model) || (clockStrategy - != LU)) { - result.add(new Object[]{model, dataStrategy, clockStrategy}); + if (!MODELS_WITH_UNKNOWN_SOLVER_STATUS.contains(model) + || (clockStrategy != LU)) { + result.add(new Object[] {model, dataStrategy, clockStrategy}); } } } @@ -100,14 +107,15 @@ public void initialize() throws IOException { @Test public void test() { // Act - final SafetyResult, XtaAction>, ? extends Trace, XtaAction>> status = checker.check( - UnitPrec.getInstance()); + final SafetyResult< + ? extends ARG, XtaAction>, + ? extends Trace, XtaAction>> + status = checker.check(UnitPrec.getInstance()); // Assert - final ArgChecker argChecker = ArgChecker.create( - Z3LegacySolverFactory.getInstance().createSolver()); - final boolean argCheckResult = argChecker.isWellLabeled(status.getWitness()); + final ArgChecker argChecker = + ArgChecker.create(Z3LegacySolverFactory.getInstance().createSolver()); + final boolean argCheckResult = argChecker.isWellLabeled(status.getProof()); assertTrue(argCheckResult); } - } diff --git a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java index 6bbc845a97..aabfaa25e3 100644 --- a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java +++ b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaAnalysisTest.java @@ -15,18 +15,6 @@ */ package hu.bme.mit.theta.xta.analysis; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; @@ -40,27 +28,31 @@ import hu.bme.mit.theta.common.visualization.writer.GraphvizWriter; import hu.bme.mit.theta.xta.XtaSystem; import hu.bme.mit.theta.xta.dsl.XtaDslManager; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public final class XtaAnalysisTest { @Parameters(name = "{0}") public static Collection data() { - return Arrays.asList(new Object[][]{ - - {"/critical-2-25-50.xta"}, - - {"/csma-2.xta"}, - - {"/fddi-2.xta"}, - - {"/fischer-2-32-64.xta"}, - - {"/lynch-2-16.xta"}, - - {"/broadcast.xta"}, - - }); + return Arrays.asList( + new Object[][] { + {"/critical-2-25-50.xta"}, + {"/csma-2.xta"}, + {"/fddi-2.xta"}, + {"/fischer-2-32-64.xta"}, + {"/lynch-2-16.xta"}, + {"/broadcast.xta"}, + }); } @Parameter(0) @@ -72,22 +64,19 @@ public void test() throws FileNotFoundException, IOException { final XtaSystem system = XtaDslManager.createSystem(inputStream); final LTS, XtaAction> lts = XtaLts.create(system); - final Analysis, XtaAction, UnitPrec> analysis = XtaAnalysis.create( - system, - UnitAnalysis.getInstance()); - final ArgBuilder, XtaAction, UnitPrec> argBuilder = ArgBuilder.create( - lts, analysis, - s -> false); + final Analysis, XtaAction, UnitPrec> analysis = + XtaAnalysis.create(system, UnitAnalysis.getInstance()); + final ArgBuilder, XtaAction, UnitPrec> argBuilder = + ArgBuilder.create(lts, analysis, s -> false); - final ArgAbstractor, XtaAction, UnitPrec> abstractor = BasicArgAbstractor.builder( - argBuilder) - .projection(s -> s.getLocs()).build(); + final ArgAbstractor, XtaAction, UnitPrec> abstractor = + BasicArgAbstractor.builder(argBuilder).projection(s -> s.getLocs()).build(); - final ARG, XtaAction> arg = abstractor.createWitness(); + final ARG, XtaAction> arg = abstractor.createProof(); abstractor.check(arg, UnitPrec.getInstance()); System.out.println( - GraphvizWriter.getInstance().writeString(ArgVisualizer.getDefault().visualize(arg))); + GraphvizWriter.getInstance() + .writeString(ArgVisualizer.getDefault().visualize(arg))); } - } diff --git a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java index 111e451934..1c1e6fa56e 100644 --- a/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java +++ b/subprojects/xta/xta-analysis/src/test/java/hu/bme/mit/theta/xta/analysis/XtaZoneAnalysisTest.java @@ -15,19 +15,6 @@ */ package hu.bme.mit.theta.xta.analysis; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.stream.Collectors; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; - import hu.bme.mit.theta.analysis.Analysis; import hu.bme.mit.theta.analysis.LTS; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; @@ -46,25 +33,31 @@ import hu.bme.mit.theta.xta.analysis.expl.XtaExplAnalysis; import hu.bme.mit.theta.xta.analysis.zone.XtaZoneAnalysis; import hu.bme.mit.theta.xta.dsl.XtaDslManager; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.stream.Collectors; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public final class XtaZoneAnalysisTest { @Parameters(name = "{0}") public static Collection data() { - return Arrays.asList(new Object[][]{ - - {"/csma-2.xta"}, - - {"/fddi-2.xta"}, - - {"/fischer-2-32-64.xta"}, - - {"/lynch-2-16.xta"}, - - {"/broadcast.xta"}, - - }); + return Arrays.asList( + new Object[][] { + {"/csma-2.xta"}, + {"/fddi-2.xta"}, + {"/fischer-2-32-64.xta"}, + {"/lynch-2-16.xta"}, + {"/broadcast.xta"}, + }); } @Parameter(0) @@ -76,30 +69,32 @@ public void test() throws FileNotFoundException, IOException { final XtaSystem system = XtaDslManager.createSystem(inputStream); final LTS, XtaAction> lts = XtaLts.create(system); - final Analysis explAnalysis = XtaExplAnalysis.create( - system); + final Analysis explAnalysis = + XtaExplAnalysis.create(system); final Analysis zoneAnalysis = XtaZoneAnalysis.getInstance(); - final Analysis, XtaAction, Prod2Prec> prodAnalysis = Prod2Analysis - .create(explAnalysis, zoneAnalysis); - final Analysis, XtaAction, ZonePrec> mappedAnalysis = PrecMappingAnalysis - .create(prodAnalysis, z -> Prod2Prec.of(UnitPrec.getInstance(), z)); - final Analysis>, XtaAction, ZonePrec> analysis = XtaAnalysis - .create(system, mappedAnalysis); + final Analysis, XtaAction, Prod2Prec> + prodAnalysis = Prod2Analysis.create(explAnalysis, zoneAnalysis); + final Analysis, XtaAction, ZonePrec> mappedAnalysis = + PrecMappingAnalysis.create( + prodAnalysis, z -> Prod2Prec.of(UnitPrec.getInstance(), z)); + final Analysis>, XtaAction, ZonePrec> analysis = + XtaAnalysis.create(system, mappedAnalysis); final ZonePrec prec = ZonePrec.of(system.getClockVars()); - final ArgBuilder>, XtaAction, ZonePrec> argBuilder = ArgBuilder - .create(lts, analysis, s -> false); + final ArgBuilder>, XtaAction, ZonePrec> + argBuilder = ArgBuilder.create(lts, analysis, s -> false); - final ArgAbstractor>, XtaAction, ZonePrec> abstractor = BasicArgAbstractor - .builder(argBuilder).projection(s -> s.getLocs()).build(); + final ArgAbstractor>, XtaAction, ZonePrec> + abstractor = + BasicArgAbstractor.builder(argBuilder).projection(s -> s.getLocs()).build(); - final ARG>, XtaAction> arg = abstractor.createWitness(); + final ARG>, XtaAction> arg = + abstractor.createProof(); abstractor.check(arg, prec); System.out.println(arg.getNodes().collect(Collectors.toSet())); System.out.println(arg.getNodes().count()); } - } diff --git a/subprojects/xta/xta-cli/src/main/java/hu/bme/mit/theta/xta/cli/XtaCli.java b/subprojects/xta/xta-cli/src/main/java/hu/bme/mit/theta/xta/cli/XtaCli.java index 4bf1694ff4..7f5185f6fb 100644 --- a/subprojects/xta/xta-cli/src/main/java/hu/bme/mit/theta/xta/cli/XtaCli.java +++ b/subprojects/xta/xta-cli/src/main/java/hu/bme/mit/theta/xta/cli/XtaCli.java @@ -15,12 +15,9 @@ */ package hu.bme.mit.theta.xta.cli; -import java.io.*; - import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; - import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.analysis.Trace; @@ -42,6 +39,7 @@ import hu.bme.mit.theta.xta.analysis.lazy.LazyXtaCheckerFactory; import hu.bme.mit.theta.xta.analysis.lazy.LazyXtaStatistics; import hu.bme.mit.theta.xta.dsl.XtaDslManager; +import java.io.*; public final class XtaCli { @@ -49,29 +47,44 @@ public final class XtaCli { private final String[] args; private final TableWriter writer; - @Parameter(names = {"--model", "-m"}, description = "Path of the input model", required = true) + @Parameter( + names = {"--model", "-m"}, + description = "Path of the input model", + required = true) String model; - @Parameter(names = {"--discrete", - "-d"}, description = "Refinement strategy for discrete variables", required = false) + @Parameter( + names = {"--discrete", "-d"}, + description = "Refinement strategy for discrete variables", + required = false) DataStrategy dataStrategy = DataStrategy.NONE; - @Parameter(names = {"--clock", - "-c"}, description = "Refinement strategy for clock variables", required = true) + @Parameter( + names = {"--clock", "-c"}, + description = "Refinement strategy for clock variables", + required = true) ClockStrategy clockStrategy; - @Parameter(names = {"--search", "-s"}, description = "Search strategy", required = true) + @Parameter( + names = {"--search", "-s"}, + description = "Search strategy", + required = true) SearchStrategy searchStrategy; - @Parameter(names = {"--benchmark", "-b"}, description = "Benchmark mode (only print metrics)") + @Parameter( + names = {"--benchmark", "-b"}, + description = "Benchmark mode (only print metrics)") Boolean benchmarkMode = false; - @Parameter(names = {"--visualize", - "-v"}, description = "Write proof or counterexample to file in dot format") + @Parameter( + names = {"--visualize", "-v"}, + description = "Write proof or counterexample to file in dot format") String dotfile = null; - @Parameter(names = {"--header", - "-h"}, description = "Print only a header (for benchmarks)", help = true) + @Parameter( + names = {"--header", "-h"}, + description = "Print only a header (for benchmarks)", + help = true) boolean headerOnly = false; @Parameter(names = "--stacktrace", description = "Print full stack trace in case of exception") @@ -112,10 +125,12 @@ private void run() { try { final XtaSystem system = loadModel(); - final SafetyChecker checker = LazyXtaCheckerFactory.create(system, - dataStrategy, - clockStrategy, searchStrategy); - final SafetyResult, ? extends Trace> result = check(checker); + final SafetyChecker checker = + LazyXtaCheckerFactory.create( + system, dataStrategy, clockStrategy, searchStrategy); + final SafetyResult< + ? extends ARG, ? extends Trace> + result = check(checker); printResult(result); if (dotfile != null) { writeVisualStatus(result, dotfile); @@ -126,13 +141,20 @@ private void run() { } } - private SafetyResult, ? extends Trace> check(SafetyChecker checker) throws Exception { + private SafetyResult, ? extends Trace> + check(SafetyChecker checker) throws Exception { try { - return (SafetyResult, ? extends Trace>) checker.check(UnitPrec.getInstance()); + return (SafetyResult< + ? extends ARG, + ? extends Trace>) + checker.check(UnitPrec.getInstance()); } catch (final Exception ex) { String message = ex.getMessage() == null ? "(no message)" : ex.getMessage(); throw new Exception( - "Error while running algorithm: " + ex.getClass().getSimpleName() + " " + message, + "Error while running algorithm: " + + ex.getClass().getSimpleName() + + " " + + message, ex); } } @@ -147,7 +169,8 @@ private XtaSystem loadModel() throws Exception { } } - private void printResult(final SafetyResult, ? extends Trace> result) { + private void printResult( + final SafetyResult, ? extends Trace> result) { final LazyXtaStatistics stats = (LazyXtaStatistics) result.getStats().get(); if (benchmarkMode) { stats.writeData(writer); @@ -173,12 +196,16 @@ private void printError(final Throwable ex) { } } - private void writeVisualStatus(final SafetyResult, ? extends Trace> status, final String filename) + private void writeVisualStatus( + final SafetyResult< + ? extends ARG, ? extends Trace> + status, + final String filename) throws FileNotFoundException { final Graph graph = - status.isSafe() ? ArgVisualizer.getDefault().visualize(status.asSafe().getWitness()) + status.isSafe() + ? ArgVisualizer.getDefault().visualize(status.asSafe().getProof()) : TraceVisualizer.getDefault().visualize(status.asUnsafe().getCex()); GraphvizWriter.getInstance().writeFile(graph, filename); } - } From 35dee48f3e9b7cbf2734609b10a30a6641541ea0 Mon Sep 17 00:00:00 2001 From: RipplB Date: Wed, 16 Oct 2024 22:31:29 +0200 Subject: [PATCH 03/21] Further generalize refiners Refiners and all their links don't need state and action generics specified anymore --- .../algorithm/cegar/ArgCegarChecker.java | 23 +- .../analysis/algorithm/cegar/ArgRefiner.java | 4 +- .../algorithm/cegar/CegarChecker.java | 72 +++-- .../analysis/algorithm/cegar/Refiner.java | 14 +- .../algorithm/cegar/RefinerResult.java | 51 ++-- .../expr/refinement/AasporRefiner.java | 51 ++-- .../refinement/MultiExprTraceRefiner.java | 71 +++-- .../refinement/SingleExprTraceRefiner.java | 60 ++-- .../analysis/XcfaSingeExprTraceRefiner.kt | 283 ++++++++++-------- 9 files changed, 353 insertions(+), 276 deletions(-) diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java index 06260c732c..8ac9d3a5a7 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgCegarChecker.java @@ -25,24 +25,25 @@ import hu.bme.mit.theta.common.logging.NullLogger; /** - * Counterexample-Guided Abstraction Refinement (CEGAR) loop implementation, - * that uses an Abstractor to explore the abstract state space and a Refiner to - * check counterexamples and refine them if needed. It also provides certain - * statistics about its execution. + * Counterexample-Guided Abstraction Refinement (CEGAR) loop implementation, that uses an Abstractor + * to explore the abstract state space and a Refiner to check counterexamples and refine them if + * needed. It also provides certain statistics about its execution. */ public final class ArgCegarChecker { - private ArgCegarChecker() { - } + private ArgCegarChecker() {} - public static CegarChecker, Trace> create( - final ArgAbstractor abstractor, final ArgRefiner refiner) { + public static + CegarChecker, Trace> create( + final ArgAbstractor abstractor, final ArgRefiner refiner) { return create(abstractor, refiner, NullLogger.getInstance()); } - public static CegarChecker, Trace> create( - final ArgAbstractor abstractor, final ArgRefiner refiner, final Logger logger) { + public static + CegarChecker, Trace> create( + final ArgAbstractor abstractor, + final ArgRefiner refiner, + final Logger logger) { return CegarChecker.create(abstractor, refiner, logger, ArgVisualizer.getDefault()); } - } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java index 2683a2fd0f..afb07b11c7 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/ArgRefiner.java @@ -25,5 +25,5 @@ * Common interface for refiners. It takes an ARG and a precision, checks if the counterexample in * the ARG is feasible and if not, it refines the precision and may also prune the ARG. */ -public interface ArgRefiner extends Refiner, Trace> { -} +public interface ArgRefiner + extends Refiner, Trace> {} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java index 30da9a28e5..dac497e043 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/CegarChecker.java @@ -15,11 +15,11 @@ */ package hu.bme.mit.theta.analysis.algorithm.cegar; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.base.Stopwatch; -import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; -import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.analysis.algorithm.Proof; import hu.bme.mit.theta.analysis.algorithm.SafetyChecker; import hu.bme.mit.theta.analysis.algorithm.SafetyResult; @@ -31,26 +31,27 @@ import hu.bme.mit.theta.common.logging.NullLogger; import hu.bme.mit.theta.common.visualization.writer.JSONWriter; import hu.bme.mit.theta.common.visualization.writer.WebDebuggerLogger; - import java.util.concurrent.TimeUnit; -import static com.google.common.base.Preconditions.checkNotNull; - /** - * Counterexample-Guided Abstraction Refinement (CEGAR) loop implementation, - * that uses an Abstractor to explore the abstract state space and a Refiner to - * check counterexamples and refine them if needed. It also provides certain - * statistics about its execution. + * Counterexample-Guided Abstraction Refinement (CEGAR) loop implementation, that uses an Abstractor + * to explore the abstract state space and a Refiner to check counterexamples and refine them if + * needed. It also provides certain statistics about its execution. */ -public final class CegarChecker implements SafetyChecker { +public final class CegarChecker

+ implements SafetyChecker { private final Abstractor abstractor; - private final Refiner refiner; + private final Refiner refiner; private final Logger logger; private final Pr proof; private final ProofVisualizer proofVisualizer; - private CegarChecker(final Abstractor abstractor, final Refiner refiner, final Logger logger, final ProofVisualizer proofVisualizer) { + private CegarChecker( + final Abstractor abstractor, + final Refiner refiner, + final Logger logger, + final ProofVisualizer proofVisualizer) { this.abstractor = checkNotNull(abstractor); this.refiner = checkNotNull(refiner); this.logger = checkNotNull(logger); @@ -58,13 +59,18 @@ private CegarChecker(final Abstractor abstractor, final Refiner CegarChecker create( - final Abstractor abstractor, final Refiner refiner, final ProofVisualizer proofVisualizer) { + public static

CegarChecker create( + final Abstractor abstractor, + final Refiner refiner, + final ProofVisualizer proofVisualizer) { return create(abstractor, refiner, NullLogger.getInstance(), proofVisualizer); } - public static CegarChecker create( - final Abstractor abstractor, final Refiner refiner, final Logger logger, final ProofVisualizer proofVisualizer) { + public static

CegarChecker create( + final Abstractor abstractor, + final Refiner refiner, + final Logger logger, + final ProofVisualizer proofVisualizer) { return new CegarChecker<>(abstractor, refiner, logger, proofVisualizer); } @@ -78,7 +84,7 @@ public SafetyResult check(final P initPrec) { final Stopwatch stopwatch = Stopwatch.createStarted(); long abstractorTime = 0; long refinerTime = 0; - RefinerResult refinerResult = null; + RefinerResult refinerResult = null; AbstractorResult abstractorResult; P prec = initPrec; int iteration = 0; @@ -91,10 +97,12 @@ public SafetyResult check(final P initPrec) { final long abstractorStartTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); abstractorResult = abstractor.check(proof, prec); abstractorTime += stopwatch.elapsed(TimeUnit.MILLISECONDS) - abstractorStartTime; - logger.write(Level.MAINSTEP, "| Checking abstraction done, result: %s%n", abstractorResult); + logger.write( + Level.MAINSTEP, "| Checking abstraction done, result: %s%n", abstractorResult); if (WebDebuggerLogger.enabled()) { - String argGraph = JSONWriter.getInstance().writeString(proofVisualizer.visualize(proof)); + String argGraph = + JSONWriter.getInstance().writeString(proofVisualizer.visualize(proof)); String precString = prec.toString(); wdl.addIteration(iteration, argGraph, precString); } @@ -107,26 +115,35 @@ public SafetyResult check(final P initPrec) { final long refinerStartTime = stopwatch.elapsed(TimeUnit.MILLISECONDS); refinerResult = refiner.refine(proof, prec); refinerTime += stopwatch.elapsed(TimeUnit.MILLISECONDS) - refinerStartTime; - logger.write(Level.MAINSTEP, "Refining abstraction done, result: %s%n", refinerResult); + logger.write( + Level.MAINSTEP, "Refining abstraction done, result: %s%n", refinerResult); if (refinerResult.isSpurious()) { prec = refinerResult.asSpurious().getRefinedPrec(); } if (lastPrec.equals(prec)) { - logger.write(Level.MAINSTEP, "! Precision did NOT change in this iteration" + System.lineSeparator()); + logger.write( + Level.MAINSTEP, + "! Precision did NOT change in this iteration" + + System.lineSeparator()); } else { - logger.write(Level.MAINSTEP, "! Precision DID change in this iteration" + System.lineSeparator()); + logger.write( + Level.MAINSTEP, + "! Precision DID change in this iteration" + System.lineSeparator()); } - } } while (!abstractorResult.isSafe() && !refinerResult.isUnsafe()); stopwatch.stop(); SafetyResult cegarResult = null; - final CegarStatistics stats = new CegarStatistics(stopwatch.elapsed(TimeUnit.MILLISECONDS), abstractorTime, - refinerTime, iteration); + final CegarStatistics stats = + new CegarStatistics( + stopwatch.elapsed(TimeUnit.MILLISECONDS), + abstractorTime, + refinerTime, + iteration); assert abstractorResult.isSafe() || refinerResult.isUnsafe(); @@ -144,6 +161,9 @@ public SafetyResult check(final P initPrec) { @Override public String toString() { - return Utils.lispStringBuilder(getClass().getSimpleName()).add(abstractor).add(refiner).toString(); + return Utils.lispStringBuilder(getClass().getSimpleName()) + .add(abstractor) + .add(refiner) + .toString(); } } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java index abd645f3cf..819bd3c403 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/Refiner.java @@ -15,20 +15,16 @@ */ package hu.bme.mit.theta.analysis.algorithm.cegar; -import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; -import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.analysis.algorithm.Proof; /** - * Common interface for refiners. It takes a witness and a precision, checks if the counterexample in - * the witness is feasible and if not, it refines the precision + * Common interface for refiners. It takes a witness and a precision, checks if the counterexample + * in the witness is feasible and if not, it refines the precision */ -public interface Refiner { +public interface Refiner

{ - /** - * Checks if the counterexample in the witness is feasible. If not, refines the precision - */ - RefinerResult refine(Pr witness, P prec); + /** Checks if the counterexample in the witness is feasible. If not, refines the precision */ + RefinerResult refine(Pr witness, P prec); } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java index a4be30781e..63011b7d08 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/algorithm/cegar/RefinerResult.java @@ -15,30 +15,26 @@ */ package hu.bme.mit.theta.analysis.algorithm.cegar; -import hu.bme.mit.theta.analysis.Action; +import static com.google.common.base.Preconditions.checkNotNull; + import hu.bme.mit.theta.analysis.Cex; import hu.bme.mit.theta.analysis.Prec; -import hu.bme.mit.theta.analysis.State; import hu.bme.mit.theta.common.Utils; -import static com.google.common.base.Preconditions.checkNotNull; - /** * Represents the result of the Refiner class that can be either spurious or unsafe. In the former * case it also contains the refined precision and in the latter case the feasible counterexample. */ -public abstract class RefinerResult { +public abstract class RefinerResult

{ - protected RefinerResult() { - } + protected RefinerResult() {} /** * Create a new spurious result. * * @param refinedPrec Refined precision */ - public static Spurious spurious( - final P refinedPrec) { + public static

Spurious spurious(final P refinedPrec) { return new Spurious<>(refinedPrec); } @@ -47,8 +43,7 @@ public static * * @param cex Feasible counterexample */ - public static Unsafe unsafe( - final C cex) { + public static

Unsafe unsafe(final C cex) { return new Unsafe<>(cex); } @@ -56,15 +51,12 @@ public static public abstract boolean isUnsafe(); - public abstract Spurious asSpurious(); + public abstract Spurious asSpurious(); - public abstract Unsafe asUnsafe(); + public abstract Unsafe asUnsafe(); - /** - * Represents the spurious result with a refined precision. - */ - public static final class Spurious - extends RefinerResult { + /** Represents the spurious result with a refined precision. */ + public static final class Spurious

extends RefinerResult { private final P refinedPrec; @@ -87,14 +79,16 @@ public boolean isUnsafe() { } @Override - public Spurious asSpurious() { + public Spurious asSpurious() { return this; } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { throw new ClassCastException( - "Cannot cast " + Spurious.class.getSimpleName() + " to " + "Cannot cast " + + Spurious.class.getSimpleName() + + " to " + Unsafe.class.getSimpleName()); } @@ -106,11 +100,8 @@ public String toString() { } } - /** - * Represents the unsafe result with a feasible counterexample. - */ - public static final class Unsafe extends - RefinerResult { + /** Represents the unsafe result with a feasible counterexample. */ + public static final class Unsafe

extends RefinerResult { private final C cex; @@ -133,14 +124,16 @@ public boolean isUnsafe() { } @Override - public Spurious asSpurious() { + public Spurious asSpurious() { throw new ClassCastException( - "Cannot cast " + Unsafe.class.getSimpleName() + " to " + "Cannot cast " + + Unsafe.class.getSimpleName() + + " to " + Spurious.class.getSimpleName()); } @Override - public Unsafe asUnsafe() { + public Unsafe asUnsafe() { return this; } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java index f1f7430241..69b184e8b6 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/AasporRefiner.java @@ -24,13 +24,13 @@ import hu.bme.mit.theta.analysis.expr.ExprAction; import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.core.decl.VarDecl; - import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -public final class AasporRefiner implements ArgRefiner { +public final class AasporRefiner + implements ArgRefiner { private final ArgRefiner refiner; @@ -38,38 +38,51 @@ public final class AasporRefiner, Set> ignoredVarRegistry; - private AasporRefiner(final ArgRefiner refiner, - final PruneStrategy pruneStrategy, - final Map, Set> ignoredVarRegistry) { + private AasporRefiner( + final ArgRefiner refiner, + final PruneStrategy pruneStrategy, + final Map, Set> ignoredVarRegistry) { this.refiner = refiner; this.pruneStrategy = pruneStrategy; this.ignoredVarRegistry = ignoredVarRegistry; } - public static AasporRefiner create( - final ArgRefiner refiner, final PruneStrategy pruneStrategy, - final Map, Set> ignoredVarRegistry) { + public static + AasporRefiner create( + final ArgRefiner refiner, + final PruneStrategy pruneStrategy, + final Map, Set> ignoredVarRegistry) { return new AasporRefiner<>(refiner, pruneStrategy, ignoredVarRegistry); } @Override - public RefinerResult> refine(final ARG arg, final P prec) { - final RefinerResult> result = refiner.refine(arg, prec); + public RefinerResult> refine(final ARG arg, final P prec) { + final RefinerResult> result = refiner.refine(arg, prec); if (result.isUnsafe() || pruneStrategy != PruneStrategy.LAZY) return result; final P newPrec = result.asSpurious().getRefinedPrec(); final Set> newlyAddedVars = new HashSet<>(newPrec.getUsedVars()); newlyAddedVars.removeAll(prec.getUsedVars()); - newlyAddedVars.forEach(newVar -> { - if (ignoredVarRegistry.containsKey(newVar)) { - Set> nodesToReExpand = ignoredVarRegistry.get(newVar).stream().flatMap(stateToPrune -> - arg.getNodes().filter(node -> node.getState().equals(stateToPrune)) // TODO one state can be in one ARG node? - ).collect(Collectors.toSet()); - nodesToReExpand.forEach(arg::markForReExpansion); - ignoredVarRegistry.remove(newVar); - } - }); + newlyAddedVars.forEach( + newVar -> { + if (ignoredVarRegistry.containsKey(newVar)) { + Set> nodesToReExpand = + ignoredVarRegistry.get(newVar).stream() + .flatMap( + stateToPrune -> + arg.getNodes() + .filter( + node -> + node.getState() + .equals( + stateToPrune)) // TODO one state can be in one ARG node? + ) + .collect(Collectors.toSet()); + nodesToReExpand.forEach(arg::markForReExpansion); + ignoredVarRegistry.remove(newVar); + } + }); return result; } diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java index b2cee796d0..71b8799468 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/MultiExprTraceRefiner.java @@ -15,6 +15,8 @@ */ package hu.bme.mit.theta.analysis.expr.refinement; +import static com.google.common.base.Preconditions.checkNotNull; + import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.Trace; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; @@ -26,14 +28,11 @@ import hu.bme.mit.theta.analysis.expr.ExprState; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; - import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import static com.google.common.base.Preconditions.checkNotNull; - -public final class MultiExprTraceRefiner +public final class MultiExprTraceRefiner< + S extends ExprState, A extends ExprAction, P extends Prec, R extends Refutation> implements ArgRefiner { private final ExprTraceChecker exprTraceChecker; @@ -42,9 +41,11 @@ public final class MultiExprTraceRefiner nodePruner; private final Logger logger; - private MultiExprTraceRefiner(final ExprTraceChecker exprTraceChecker, - final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger) { + private MultiExprTraceRefiner( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger) { this.exprTraceChecker = checkNotNull(exprTraceChecker); this.precRefiner = checkNotNull(precRefiner); this.pruneStrategy = checkNotNull(pruneStrategy); @@ -52,10 +53,12 @@ private MultiExprTraceRefiner(final ExprTraceChecker exprTraceChecker, this.logger = checkNotNull(logger); } - private MultiExprTraceRefiner(final ExprTraceChecker exprTraceChecker, - final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger, - final NodePruner nodePruner) { + private MultiExprTraceRefiner( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger, + final NodePruner nodePruner) { this.exprTraceChecker = checkNotNull(exprTraceChecker); this.precRefiner = checkNotNull(precRefiner); this.pruneStrategy = checkNotNull(pruneStrategy); @@ -63,20 +66,28 @@ private MultiExprTraceRefiner(final ExprTraceChecker exprTraceChecker, this.logger = checkNotNull(logger); } - public static MultiExprTraceRefiner create( - final ExprTraceChecker exprTraceChecker, final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger) { + public static + MultiExprTraceRefiner create( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger) { return new MultiExprTraceRefiner<>(exprTraceChecker, precRefiner, pruneStrategy, logger); } - public static MultiExprTraceRefiner create( - final ExprTraceChecker exprTraceChecker, final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger, final NodePruner nodePruner) { - return new MultiExprTraceRefiner<>(exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner); + public static + MultiExprTraceRefiner create( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger, + final NodePruner nodePruner) { + return new MultiExprTraceRefiner<>( + exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner); } @Override - public RefinerResult> refine(final ARG arg, final P prec) { + public RefinerResult> refine(final ARG arg, final P prec) { checkNotNull(arg); checkNotNull(prec); assert !arg.isSafe() : "ARG must be unsafe"; @@ -100,13 +111,18 @@ public RefinerResult> refine(final ARG arg, final P p if (cexStatuses.stream().anyMatch(ExprTraceStatus::isFeasible)) { logger.write(Level.SUBSTEP, "done, result: found feasible%n"); - return RefinerResult.unsafe(traces.get( - cexStatuses.indexOf(cexStatuses.stream().filter(ExprTraceStatus::isFeasible).findFirst().get()))); + return RefinerResult.unsafe( + traces.get( + cexStatuses.indexOf( + cexStatuses.stream() + .filter(ExprTraceStatus::isFeasible) + .findFirst() + .get()))); } else { assert cexStatuses.size() == cexs.size(); logger.write(Level.SUBSTEP, "done, result: all infeasible%n"); - final List refutations = cexStatuses.stream().map(s -> s.asInfeasible().getRefutation()) - .toList(); + final List refutations = + cexStatuses.stream().map(s -> s.asInfeasible().getRefutation()).toList(); assert refutations.size() == cexs.size(); final List> nodesToPrune = new ArrayList<>(traces.size()); @@ -130,7 +146,8 @@ public RefinerResult> refine(final ARG arg, final P p P refinedPrec = prec; for (int i = 0; i < refutations.size(); ++i) { if (!skip.get(i)) { - refinedPrec = precRefiner.refine(refinedPrec, traces.get(i), refutations.get(i)); + refinedPrec = + precRefiner.refine(refinedPrec, traces.get(i), refutations.get(i)); } } @@ -153,7 +170,5 @@ public RefinerResult> refine(final ARG arg, final P p logger.write(Level.SUBSTEP, "done%n"); return RefinerResult.spurious(refinedPrec); } - } - -} \ No newline at end of file +} diff --git a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java index 126f4212f4..04befdbfcb 100644 --- a/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java +++ b/subprojects/common/analysis/src/main/java/hu/bme/mit/theta/analysis/expr/refinement/SingleExprTraceRefiner.java @@ -15,6 +15,8 @@ */ package hu.bme.mit.theta.analysis.expr.refinement; +import static com.google.common.base.Preconditions.checkNotNull; + import hu.bme.mit.theta.analysis.Prec; import hu.bme.mit.theta.analysis.Trace; import hu.bme.mit.theta.analysis.algorithm.arg.ARG; @@ -27,16 +29,14 @@ import hu.bme.mit.theta.common.Utils; import hu.bme.mit.theta.common.logging.Logger; import hu.bme.mit.theta.common.logging.Logger.Level; - import java.util.Optional; -import static com.google.common.base.Preconditions.checkNotNull; - /** - * A Refiner implementation that can refine a single trace (of ExprStates and - * ExprActions) using an ExprTraceChecker and a PrecRefiner. + * A Refiner implementation that can refine a single trace (of ExprStates and ExprActions) using an + * ExprTraceChecker and a PrecRefiner. */ -public class SingleExprTraceRefiner +public class SingleExprTraceRefiner< + S extends ExprState, A extends ExprAction, P extends Prec, R extends Refutation> implements ArgRefiner { protected final ExprTraceChecker exprTraceChecker; protected final PrecRefiner precRefiner; @@ -44,9 +44,11 @@ public class SingleExprTraceRefiner nodePruner; protected final Logger logger; - protected SingleExprTraceRefiner(final ExprTraceChecker exprTraceChecker, - final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger) { + protected SingleExprTraceRefiner( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger) { this.exprTraceChecker = checkNotNull(exprTraceChecker); this.precRefiner = checkNotNull(precRefiner); this.pruneStrategy = checkNotNull(pruneStrategy); @@ -54,10 +56,12 @@ protected SingleExprTraceRefiner(final ExprTraceChecker exprTraceChecker, this.logger = checkNotNull(logger); } - protected SingleExprTraceRefiner(final ExprTraceChecker exprTraceChecker, - final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger, - final NodePruner nodePruner) { + protected SingleExprTraceRefiner( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger, + final NodePruner nodePruner) { this.exprTraceChecker = checkNotNull(exprTraceChecker); this.precRefiner = checkNotNull(precRefiner); this.pruneStrategy = checkNotNull(pruneStrategy); @@ -65,20 +69,28 @@ protected SingleExprTraceRefiner(final ExprTraceChecker exprTraceChecker, this.logger = checkNotNull(logger); } - public static SingleExprTraceRefiner create( - final ExprTraceChecker exprTraceChecker, final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger) { + public static + SingleExprTraceRefiner create( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger) { return new SingleExprTraceRefiner<>(exprTraceChecker, precRefiner, pruneStrategy, logger); } - public static SingleExprTraceRefiner create( - final ExprTraceChecker exprTraceChecker, final PrecRefiner precRefiner, - final PruneStrategy pruneStrategy, final Logger logger, final NodePruner nodePruner) { - return new SingleExprTraceRefiner<>(exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner); + public static + SingleExprTraceRefiner create( + final ExprTraceChecker exprTraceChecker, + final PrecRefiner precRefiner, + final PruneStrategy pruneStrategy, + final Logger logger, + final NodePruner nodePruner) { + return new SingleExprTraceRefiner<>( + exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner); } @Override - public RefinerResult> refine(final ARG arg, final P prec) { + public RefinerResult> refine(final ARG arg, final P prec) { checkNotNull(arg); checkNotNull(prec); assert !arg.isSafe() : "ARG must be unsafe"; @@ -127,7 +139,9 @@ public RefinerResult> refine(final ARG arg, final P p @Override public String toString() { - return Utils.lispStringBuilder(getClass().getSimpleName()).add(exprTraceChecker).add(precRefiner).toString(); + return Utils.lispStringBuilder(getClass().getSimpleName()) + .add(exprTraceChecker) + .add(precRefiner) + .toString(); } - } diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt index 93410e0641..4ca545dd9b 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaSingeExprTraceRefiner.kt @@ -29,143 +29,168 @@ import hu.bme.mit.theta.analysis.ptr.patch import hu.bme.mit.theta.common.logging.Logger import java.util.* - class XcfaSingleExprTraceRefiner : - SingleExprTraceRefiner { - - private constructor( - exprTraceChecker: ExprTraceChecker, - precRefiner: PrecRefiner, - pruneStrategy: PruneStrategy, - logger: Logger - ) : super(exprTraceChecker, precRefiner, pruneStrategy, logger) - - private constructor( - exprTraceChecker: ExprTraceChecker, - precRefiner: PrecRefiner, - pruneStrategy: PruneStrategy, - logger: Logger, - nodePruner: NodePruner - ) : super(exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner) - - private fun findPoppedState(trace: Trace): Pair>? { - trace.states.forEachIndexed { i, s -> - val state = s as XcfaState - state.processes.entries.find { (_, processState) -> processState.popped != null } - ?.let { (pid, processState) -> - val stackBeforePop = LinkedList(processState.locs) - stackBeforePop.push(processState.popped) - val processesBeforePop = state.processes.toMutableMap() - processesBeforePop[pid] = processState.copy(locs = stackBeforePop) - val stateBeforePop = state.copy(processes = processesBeforePop) - return Pair(i, stateBeforePop) - } + SingleExprTraceRefiner { + + private constructor( + exprTraceChecker: ExprTraceChecker, + precRefiner: PrecRefiner, + pruneStrategy: PruneStrategy, + logger: Logger, + ) : super(exprTraceChecker, precRefiner, pruneStrategy, logger) + + private constructor( + exprTraceChecker: ExprTraceChecker, + precRefiner: PrecRefiner, + pruneStrategy: PruneStrategy, + logger: Logger, + nodePruner: NodePruner, + ) : super(exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner) + + private fun findPoppedState(trace: Trace): Pair>? { + trace.states.forEachIndexed { i, s -> + val state = s as XcfaState + state.processes.entries + .find { (_, processState) -> processState.popped != null } + ?.let { (pid, processState) -> + val stackBeforePop = LinkedList(processState.locs) + stackBeforePop.push(processState.popped) + val processesBeforePop = state.processes.toMutableMap() + processesBeforePop[pid] = processState.copy(locs = stackBeforePop) + val stateBeforePop = state.copy(processes = processesBeforePop) + return Pair(i, stateBeforePop) } - return null } - - fun refineTemp(arg: ARG, prec: P?): RefinerResult> { - Preconditions.checkNotNull(arg) - Preconditions.checkNotNull(prec) - assert(!arg.isSafe) { "ARG must be unsafe" } - val optionalNewCex = arg.cexs.findFirst() - val cexToConcretize = optionalNewCex.get() - val rawTrace = cexToConcretize.toTrace() - val (_, states, actions) = rawTrace.actions.foldIndexed( - Triple(Pair(emptyMap(), 0), listOf(rawTrace.getState(0)), - listOf())) { i: Int, (wTripleCnt: Pair, states: List, actions: List): Triple, List, List>, a: A -> - val (wTriple, cnt) = wTripleCnt - val newA = (a as XcfaAction).withLastWrites(wTriple, cnt) - val newState = (rawTrace.getState(i + 1) as XcfaState>).let { - it.withState(PtrState(it.sGlobal.innerState.patch(newA.nextWriteTriples()))) - } - Triple(Pair(newA.nextWriteTriples(), newA.cnts.values.maxOrNull() ?: newA.inCnt), states + (newState as S), - actions + (newA as A)) + return null + } + + fun refineTemp(arg: ARG, prec: P?): RefinerResult> { + Preconditions.checkNotNull(arg) + Preconditions.checkNotNull(prec) + assert(!arg.isSafe) { "ARG must be unsafe" } + val optionalNewCex = arg.cexs.findFirst() + val cexToConcretize = optionalNewCex.get() + val rawTrace = cexToConcretize.toTrace() + val (_, states, actions) = + rawTrace.actions.foldIndexed( + Triple(Pair(emptyMap(), 0), listOf(rawTrace.getState(0)), listOf()) + ) { + i: Int, + (wTripleCnt: Pair, states: List, actions: List): Triple< + Pair, + List, + List, + >, + a: A -> + val (wTriple, cnt) = wTripleCnt + val newA = (a as XcfaAction).withLastWrites(wTriple, cnt) + val newState = + (rawTrace.getState(i + 1) as XcfaState>).let { + it.withState(PtrState(it.sGlobal.innerState.patch(newA.nextWriteTriples()))) + } + Triple( + Pair(newA.nextWriteTriples(), newA.cnts.values.maxOrNull() ?: newA.inCnt), + states + (newState as S), + actions + (newA as A), + ) + } + val traceToConcretize = Trace.of(states, actions) + + logger.write(Logger.Level.INFO, "| | Trace length: %d%n", traceToConcretize.length()) + logger.write(Logger.Level.DETAIL, "| | Trace: %s%n", traceToConcretize) + logger.write(Logger.Level.SUBSTEP, "| | Checking trace...") + val cexStatus = exprTraceChecker.check(traceToConcretize) + logger.write(Logger.Level.SUBSTEP, "done, result: %s%n", cexStatus) + assert(cexStatus.isFeasible() || cexStatus.isInfeasible()) { "Unknown CEX status" } + return if (cexStatus.isFeasible()) { + RefinerResult.unsafe(traceToConcretize) + } else { + val refutation = cexStatus.asInfeasible().refutation + logger.write(Logger.Level.DETAIL, "| | | Refutation: %s%n", refutation) + val refinedPrec = precRefiner.refine(prec, traceToConcretize, refutation) + val pruneIndex = refutation.getPruneIndex() + assert(0 <= pruneIndex) { "Pruning index must be non-negative" } + assert(pruneIndex <= cexToConcretize.length()) { "Pruning index larger than cex length" } + when (pruneStrategy) { + PruneStrategy.LAZY -> { + logger.write(Logger.Level.SUBSTEP, "| | Pruning from index %d...", pruneIndex) + val nodeToPrune = cexToConcretize.node(pruneIndex) + nodePruner.prune(arg, nodeToPrune) } - val traceToConcretize = Trace.of(states, actions) - - logger.write(Logger.Level.INFO, "| | Trace length: %d%n", traceToConcretize.length()) - logger.write(Logger.Level.DETAIL, "| | Trace: %s%n", traceToConcretize) - logger.write(Logger.Level.SUBSTEP, "| | Checking trace...") - val cexStatus = exprTraceChecker.check(traceToConcretize) - logger.write(Logger.Level.SUBSTEP, "done, result: %s%n", cexStatus) - assert(cexStatus.isFeasible() || cexStatus.isInfeasible()) { "Unknown CEX status" } - return if (cexStatus.isFeasible()) { - RefinerResult.unsafe(traceToConcretize) - } else { - val refutation = cexStatus.asInfeasible().refutation - logger.write(Logger.Level.DETAIL, "| | | Refutation: %s%n", refutation) - val refinedPrec = precRefiner.refine(prec, traceToConcretize, refutation) - val pruneIndex = refutation.getPruneIndex() - assert(0 <= pruneIndex) { "Pruning index must be non-negative" } - assert(pruneIndex <= cexToConcretize.length()) { "Pruning index larger than cex length" } - when (pruneStrategy) { - PruneStrategy.LAZY -> { - logger.write(Logger.Level.SUBSTEP, "| | Pruning from index %d...", pruneIndex) - val nodeToPrune = cexToConcretize.node(pruneIndex) - nodePruner.prune(arg, nodeToPrune) - } - - PruneStrategy.FULL -> { - logger.write(Logger.Level.SUBSTEP, "| | Pruning whole ARG", pruneIndex) - arg.pruneAll() - } - - else -> throw java.lang.UnsupportedOperationException("Unsupported pruning strategy") - } - logger.write(Logger.Level.SUBSTEP, "done%n") - RefinerResult.spurious(refinedPrec) + + PruneStrategy.FULL -> { + logger.write(Logger.Level.SUBSTEP, "| | Pruning whole ARG", pruneIndex) + arg.pruneAll() } - } - override fun refine(arg: ARG, prec: P?): RefinerResult> { - Preconditions.checkNotNull(arg) - Preconditions.checkNotNull

(prec) - assert(!arg.isSafe) { "ARG must be unsafe" } - - val optionalNewCex = arg.cexs.findFirst() - val cexToConcretize = optionalNewCex.get() - val traceToConcretize = cexToConcretize.toTrace() - - val refinerResult = refineTemp(arg, prec) //super.refine(arg, prec) - val checkForPop = !(traceToConcretize.states.first() as XcfaState<*>).xcfa!!.isInlined - - return if (checkForPop && refinerResult.isUnsafe) findPoppedState(traceToConcretize)?.let { (i, state) -> - when (pruneStrategy) { - PruneStrategy.LAZY -> { - logger.write(Logger.Level.SUBSTEP, "| | Pruning from index %d...", i) - val nodeToPrune = cexToConcretize.node(i) - nodePruner.prune(arg, nodeToPrune) - } - - PruneStrategy.FULL -> { - logger.write(Logger.Level.SUBSTEP, "| | Pruning whole ARG", i) - arg.pruneAll() - } - - else -> throw UnsupportedOperationException("Unsupported pruning strategy") - } - - val refinedPrec = (prec as XcfaPrec

).copy() - refinedPrec.noPop.add(state) - RefinerResult.spurious(refinedPrec as P?) - } ?: refinerResult else refinerResult + else -> throw java.lang.UnsupportedOperationException("Unsupported pruning strategy") + } + logger.write(Logger.Level.SUBSTEP, "done%n") + RefinerResult.spurious(refinedPrec) } - - companion object { - - fun create( - exprTraceChecker: ExprTraceChecker, precRefiner: PrecRefiner, - pruneStrategy: PruneStrategy, logger: Logger - ): XcfaSingleExprTraceRefiner { - return XcfaSingleExprTraceRefiner(exprTraceChecker, precRefiner, pruneStrategy, logger) + } + + override fun refine(arg: ARG, prec: P?): RefinerResult> { + Preconditions.checkNotNull(arg) + Preconditions.checkNotNull

(prec) + assert(!arg.isSafe) { "ARG must be unsafe" } + + val optionalNewCex = arg.cexs.findFirst() + val cexToConcretize = optionalNewCex.get() + val traceToConcretize = cexToConcretize.toTrace() + + val refinerResult = refineTemp(arg, prec) // super.refine(arg, prec) + val checkForPop = !(traceToConcretize.states.first() as XcfaState<*>).xcfa!!.isInlined + + return if (checkForPop && refinerResult.isUnsafe) + findPoppedState(traceToConcretize)?.let { (i, state) -> + when (pruneStrategy) { + PruneStrategy.LAZY -> { + logger.write(Logger.Level.SUBSTEP, "| | Pruning from index %d...", i) + val nodeToPrune = cexToConcretize.node(i) + nodePruner.prune(arg, nodeToPrune) + } + + PruneStrategy.FULL -> { + logger.write(Logger.Level.SUBSTEP, "| | Pruning whole ARG", i) + arg.pruneAll() + } + + else -> throw UnsupportedOperationException("Unsupported pruning strategy") } - fun create( - exprTraceChecker: ExprTraceChecker, precRefiner: PrecRefiner, - pruneStrategy: PruneStrategy, logger: Logger, nodePruner: NodePruner - ): XcfaSingleExprTraceRefiner { - return XcfaSingleExprTraceRefiner(exprTraceChecker, precRefiner, pruneStrategy, logger, nodePruner) - } + val refinedPrec = (prec as XcfaPrec

).copy() + refinedPrec.noPop.add(state) + RefinerResult.spurious(refinedPrec as P?) + } ?: refinerResult + else refinerResult + } + + companion object { + + fun create( + exprTraceChecker: ExprTraceChecker, + precRefiner: PrecRefiner, + pruneStrategy: PruneStrategy, + logger: Logger, + ): XcfaSingleExprTraceRefiner { + return XcfaSingleExprTraceRefiner(exprTraceChecker, precRefiner, pruneStrategy, logger) + } + + fun create( + exprTraceChecker: ExprTraceChecker, + precRefiner: PrecRefiner, + pruneStrategy: PruneStrategy, + logger: Logger, + nodePruner: NodePruner, + ): XcfaSingleExprTraceRefiner { + return XcfaSingleExprTraceRefiner( + exprTraceChecker, + precRefiner, + pruneStrategy, + logger, + nodePruner, + ) } + } } From 4defa73ad2b0fe23883364eb6edd12e460edcbdc Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Thu, 31 Oct 2024 18:33:01 +0100 Subject: [PATCH 04/21] Added kaml-serialization plugin --- buildSrc/build.gradle.kts | 1 + buildSrc/gradle.properties | 3 ++- buildSrc/src/main/kotlin/Deps.kt | 2 ++ .../main/kotlin/kaml-serialization.gradle.kts | 20 +++++++++++++++++++ subprojects/xcfa/xcfa-cli/build.gradle.kts | 1 + 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/kotlin/kaml-serialization.gradle.kts diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 7b1e3380f6..114d14bf7a 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -38,6 +38,7 @@ fun gradlePlugin(id: String, version: String): String = "$id:$id.gradle.plugin:$ dependencies { compileOnly(gradleKotlinDsl()) implementation(kotlin("gradle-plugin", kotlinVersion)) + implementation(kotlin("serialization", kotlinVersion)) implementation(gradlePlugin("com.github.johnrengelman.shadow", shadowVersion)) implementation(gradlePlugin("com.diffplug.spotless", spotlessVersion)) } diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index 77da25281b..f25e464eeb 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -40,4 +40,5 @@ gsonVersion=2.9.1 javasmtVersion=4.1.1 sosylabVersion=0.3000-569-g89796f98 cliktVersion=4.4.0 -spotlessVersion=6.25.0 \ No newline at end of file +spotlessVersion=6.25.0 +kamlVersion=0.62.1 \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt index 642499ed8f..5fc6cc9b53 100644 --- a/buildSrc/src/main/kotlin/Deps.kt +++ b/buildSrc/src/main/kotlin/Deps.kt @@ -79,4 +79,6 @@ object Deps { } val clikt = "com.github.ajalt.clikt:clikt:${Versions.clikt}" + + val kaml = "com.charleskorn.kaml:kaml:${Versions.kaml}" } diff --git a/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts b/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts new file mode 100644 index 0000000000..c2974cb03e --- /dev/null +++ b/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts @@ -0,0 +1,20 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply(plugin = "kotlin-common") +plugins { + kotlin("plugin.serialization") +} \ No newline at end of file diff --git a/subprojects/xcfa/xcfa-cli/build.gradle.kts b/subprojects/xcfa/xcfa-cli/build.gradle.kts index f695b775af..83c5989fe7 100644 --- a/subprojects/xcfa/xcfa-cli/build.gradle.kts +++ b/subprojects/xcfa/xcfa-cli/build.gradle.kts @@ -16,6 +16,7 @@ plugins { id("kotlin-common") + id("kaml-serialization") id("cli-tool") } From 0bc0f4dfe52bc57b2c4a799fc58939d3e887ff9e Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:23:19 +0100 Subject: [PATCH 05/21] Downgraded kaml --- buildSrc/gradle.properties | 2 +- .../main/kotlin/kaml-serialization.gradle.kts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/buildSrc/gradle.properties b/buildSrc/gradle.properties index f25e464eeb..efb2dbd0eb 100644 --- a/buildSrc/gradle.properties +++ b/buildSrc/gradle.properties @@ -41,4 +41,4 @@ javasmtVersion=4.1.1 sosylabVersion=0.3000-569-g89796f98 cliktVersion=4.4.0 spotlessVersion=6.25.0 -kamlVersion=0.62.1 \ No newline at end of file +kamlVersion=0.59.0 \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts b/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts index c2974cb03e..b3e7da0b1c 100644 --- a/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts +++ b/buildSrc/src/main/kotlin/kaml-serialization.gradle.kts @@ -1,3 +1,21 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import gradle.kotlin.dsl.accessors._07de9d51edfbede3e6fa517ade9dcf20.implementation + /* * Copyright 2024 Budapest University of Technology and Economics * @@ -17,4 +35,7 @@ apply(plugin = "kotlin-common") plugins { kotlin("plugin.serialization") +} +dependencies { + implementation(Deps.kaml) } \ No newline at end of file From 65a557b80ba32597b3b343a042ee71dd7204ac4f Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:32:21 +0100 Subject: [PATCH 06/21] Updated metadata collection --- .../grammar/function/FunctionVisitor.java | 15 ++++++++++++++- .../model/statements/CStatement.java | 10 ++++++++++ .../java/hu/bme/mit/theta/c2xcfa/CMetaData.kt | 4 +++- .../mit/theta/c2xcfa/FrontendXcfaBuilder.kt | 19 +++++++++++-------- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java index 4f9041fa08..e4dbd1a5c8 100644 --- a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java +++ b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java @@ -74,6 +74,8 @@ public class FunctionVisitor extends CBaseVisitor { private final TypedefVisitor typedefVisitor; private final Logger uniqueWarningLogger; + private ParserRuleContext currentStatementContext = null; + public void clear() { variables.clear(); flatVariables.clear(); @@ -168,6 +170,9 @@ public CStatement visitCompilationUnit(CParser.CompilationUnitContext ctx) { } public void recordMetadata(ParserRuleContext ctx, CStatement statement) { + if (currentStatementContext != null) { + ctx = currentStatementContext; // this will overwrite the current ASt element's ctx with the statement's ctx + } Token start = ctx.getStart(); Token stop = ctx.getStop(); String stopText = stop.getText(); @@ -186,6 +191,7 @@ public void recordMetadata(ParserRuleContext ctx, CStatement statement) { statement.setOffsetStart(offsetStart); statement.setOffsetEnd(offsetEnd); statement.setSourceText(textWithWS(ctx)); + statement.setCtx(ctx); } @@ -258,7 +264,10 @@ public CStatement visitBlockItemList(CParser.BlockItemListContext ctx) { if (ctx.parent.parent.parent.parent instanceof CParser.BlockItemListContext) variables.push(Tuple2.of("anonymous" + anonCnt++, new LinkedHashMap<>())); for (CParser.BlockItemContext blockItemContext : ctx.blockItem()) { + final var save = currentStatementContext; + currentStatementContext = blockItemContext; compound.getcStatementList().add(blockItemContext.accept(this)); + currentStatementContext = save; } if (ctx.parent.parent.parent.parent instanceof CParser.BlockItemListContext) variables.pop(); @@ -420,7 +429,11 @@ public CStatement visitReturnStatement(CParser.ReturnStatementContext ctx) { @Override public CStatement visitStatement(CParser.StatementContext ctx) { - return ctx.children.get(0).accept(this); + final var save = currentStatementContext; + currentStatementContext = ctx; + final var ret = ctx.children.get(0).accept(this); + currentStatementContext = save; + return ret; } @Override diff --git a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java index 93a2199239..7b569aada4 100644 --- a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java +++ b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java @@ -19,6 +19,7 @@ import hu.bme.mit.theta.core.type.Expr; import hu.bme.mit.theta.frontend.ParseContext; import hu.bme.mit.theta.frontend.UnsupportedFrontendElementException; +import org.antlr.v4.runtime.ParserRuleContext; /** * Every Program, Function and Statement is a subclass of this base class. @@ -39,6 +40,7 @@ public abstract class CStatement { private int offsetStart = -1; private int offsetEnd = -1; private String sourceText = ""; + private ParserRuleContext ctx; protected CStatement(ParseContext parseContext) { this.parseContext = parseContext; @@ -137,4 +139,12 @@ public String getSourceText() { public void setSourceText(String sourceText) { this.sourceText = sourceText; } + + public ParserRuleContext getCtx() { + return ctx; + } + + public void setCtx(ParserRuleContext ctx) { + this.ctx = ctx; + } } diff --git a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt index 10d76a8e8d..fe8d5ee0bd 100644 --- a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt +++ b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt @@ -19,6 +19,7 @@ import hu.bme.mit.theta.xcfa.model.MetaData import hu.bme.mit.theta.xcfa.model.XcfaEdge import hu.bme.mit.theta.xcfa.model.XcfaLabel import hu.bme.mit.theta.xcfa.model.XcfaLocation +import org.antlr.v4.runtime.ParserRuleContext data class CMetaData( val lineNumberStart: Int?, @@ -27,7 +28,8 @@ data class CMetaData( val colNumberStop: Int?, val offsetStart: Int?, val offsetEnd: Int?, - val sourceText: String? + val sourceText: String?, + val ctx: ParserRuleContext?, ) : MetaData() fun XcfaLabel.getCMetaData(): CMetaData? { diff --git a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt index d82a92fa4a..33355e8144 100644 --- a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt +++ b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt @@ -76,13 +76,14 @@ class FrontendXcfaBuilder(val parseContext: ParseContext, val checkOverflow: Boo } private fun getMetadata(source: CStatement): CMetaData = CMetaData( - lineNumberStart = source.lineNumberStart, - lineNumberStop = source.lineNumberStop, - colNumberStart = source.colNumberStart, - colNumberStop = source.colNumberStop, - offsetStart = source.offsetStart, - offsetEnd = source.offsetEnd, - sourceText = source.sourceText + lineNumberStart = source.lineNumberStart.takeIf { it != -1 }, + lineNumberStop = source.lineNumberStop.takeIf { it != -1 }, + colNumberStart = source.colNumberStart.takeIf { it != -1 }, + colNumberStop = source.colNumberStop.takeIf { it != -1 }, + offsetStart = source.offsetStart.takeIf { it != -1 }, + offsetEnd = source.offsetEnd.takeIf { it != -1 }, + sourceText = source.sourceText, + ctx = source.ctx, ) fun buildXcfa(cProgram: CProgram): XcfaBuilder { @@ -559,7 +560,9 @@ class FrontendXcfaBuilder(val parseContext: ParseContext, val checkOverflow: Boo var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) builder.addEdge(edge) edge = XcfaEdge(initLoc, - getLoc(builder, statement.label, metadata = getMetadata(statement))) + getLoc(builder, statement.label, metadata = getMetadata(statement)), + metadata = getMetadata(statement) + ) builder.addLoc(getLoc(builder, statement.label, metadata = getMetadata(statement))) val unreachableLoc: XcfaLocation = XcfaLocation( "Unreachable" + XcfaLocation.uniqueCounter(), metadata = getMetadata(statement)) From e6df276b9b21fb0224806c1ae6664f178f338a8d Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:33:25 +0100 Subject: [PATCH 07/21] Not allowing empty metadata by mistake --- .../hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt | 7 ++++--- .../main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt index 82a8e65178..b14d714142 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt @@ -37,9 +37,10 @@ constructor(val pid: Int, val edge: XcfaEdge, private val lastWrites: WriteTripl source: XcfaLocation, target: XcfaLocation, label: XcfaLabel = NopLabel, + metaData: MetaData = EmptyMetaData, lastWrites: WriteTriples = emptyMap(), nextCnt: Int = 0) : - this(pid, XcfaEdge(source, target, label), lastWrites, nextCnt) + this(pid, XcfaEdge(source, target, label, metaData), lastWrites, nextCnt) override val stmtList: List get() = stmts @@ -49,11 +50,11 @@ constructor(val pid: Int, val edge: XcfaEdge, private val lastWrites: WriteTripl } fun withLabel(sequenceLabel: SequenceLabel): XcfaAction { - return XcfaAction(pid, source, target, sequenceLabel, nextCnt = nextCnt) + return XcfaAction(pid, source, target, sequenceLabel, edge.metadata, nextCnt = nextCnt) } fun withLastWrites(writeTriples: WriteTriples, nextCnt: Int): XcfaAction { - return XcfaAction(pid, source, target, label, writeTriples, nextCnt) + return XcfaAction(pid, source, target, label, edge.metadata, writeTriples, nextCnt) } } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt index ba90dcdfdf..91d3d567f2 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt @@ -112,7 +112,7 @@ data class XcfaLocation @JvmOverloads constructor( val initial: Boolean = false, // is this the initial location? val final: Boolean = false, // is this the final location? val error: Boolean = false, // is this the error location? - val metadata: MetaData = EmptyMetaData, + val metadata: MetaData, ) { val incomingEdges: MutableSet = LinkedHashSet() // all incoming edges in the current procedure @@ -129,16 +129,16 @@ data class XcfaLocation @JvmOverloads constructor( } } -data class XcfaEdge @JvmOverloads constructor( +data class XcfaEdge( val source: XcfaLocation, // source location val target: XcfaLocation, // target location val label: XcfaLabel = NopLabel, // edge label - val metadata: MetaData = EmptyMetaData, + val metadata: MetaData ) { - fun withLabel(label: XcfaLabel): XcfaEdge = XcfaEdge(source, target, label) - fun withTarget(target: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label) - fun withSource(source: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label) + fun withLabel(label: XcfaLabel): XcfaEdge = XcfaEdge(source, target, label, metadata) + fun withTarget(target: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label, metadata) + fun withSource(source: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label, metadata) } data class XcfaGlobalVar @JvmOverloads constructor( From 07b92969f5cba014377a92a6ab35dc6d9b8965e6 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:34:25 +0100 Subject: [PATCH 08/21] Not swallowing edges in concretization --- .../xcfa/cli/witnesses/TraceToWitness.kt | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt index 38ab39f52b..252e248e45 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt @@ -52,6 +52,7 @@ fun traceToWitness( for (i in 0 until trace.length()) { val state = trace.states[i] + val action = trace.actions[i] val nextState = trace.states[i + 1] val newThreads = nextState.processes.keys - state.processes.keys val node = WitnessNode( @@ -68,18 +69,19 @@ fun traceToWitness( if (node != WitnessNode(id = "N${newStates.size}")) { newStates.add(node) val edge = WitnessEdge(sourceId = lastNode.id, targetId = node.id, - threadId = trace.actions[i].pid.toString()) + threadId = trace.actions[i].pid.toString(), edge = action.edge + ) newActions.add(edge) lastNode = node } - val action = trace.actions[i] val flattenedSequence = flattenSequence(action.edge.label) for (xcfaLabel in flattenedSequence) { val node = WitnessNode(id = "N${newStates.size}", entry = false, sink = false, violation = false) var edge = labelToEdge(lastNode, node, xcfaLabel, action.pid, - nextState.sGlobal.getVal(), parseContext) + nextState.sGlobal.getVal(), parseContext, action.edge + ) if (newThreads.isNotEmpty() && xcfaLabel is StartLabel) { edge = edge.copy(createThread = newThreads.joinToString(",")) } @@ -104,7 +106,7 @@ fun traceToWitness( globalState = lastState.sGlobal ) newStates.add(node) - val edge = WitnessEdge(sourceId = lastNode.id, targetId = node.id) + val edge = WitnessEdge(sourceId = lastNode.id, targetId = node.id, edge = trace.actions[trace.length() - 1].edge) newActions.add(edge) return Trace.of(newStates, newActions) @@ -120,8 +122,10 @@ fun shouldInclude(edge: WitnessEdge, verbosity: Verbosity): Boolean = } -private fun labelToEdge(lastNode: WitnessNode, node: WitnessNode, xcfaLabel: XcfaLabel, pid: Int, - valuation: Valuation, parseContext: ParseContext): WitnessEdge = +private fun labelToEdge( + lastNode: WitnessNode, node: WitnessNode, xcfaLabel: XcfaLabel, pid: Int, + valuation: Valuation, parseContext: ParseContext, edge: XcfaEdge +): WitnessEdge = WitnessEdge( sourceId = lastNode.id, targetId = node.id, @@ -147,11 +151,14 @@ private fun labelToEdge(lastNode: WitnessNode, node: WitnessNode, xcfaLabel: Xcf endline = xcfaLabel.getCMetaData()?.lineNumberStop, startoffset = xcfaLabel.getCMetaData()?.offsetStart, endoffset = xcfaLabel.getCMetaData()?.offsetEnd, + startcol = xcfaLabel.getCMetaData()?.colNumberStart, + endcol = xcfaLabel.getCMetaData()?.colNumberStop, threadId = if (pid != null) "$pid" else null, stmt = if (xcfaLabel is StmtLabel) xcfaLabel.stmt.toString() else null, - cSource = xcfaLabel.getCMetaData()?.sourceText + cSource = xcfaLabel.getCMetaData()?.sourceText, + edge = edge ) private fun flattenSequence(label: XcfaLabel): List = From 35189fc65eaffe6e0fef9b37825e5aab762907c6 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:35:16 +0100 Subject: [PATCH 09/21] Not swallowing edges in writing --- .../theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java index 5c6c8e0a96..435e3dbf9e 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java @@ -41,12 +41,7 @@ import hu.bme.mit.theta.xcfa.model.XcfaEdge; import kotlin.Triple; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; @@ -65,7 +60,7 @@ public static Trace, XcfaAction> concretize( Map, Expr, Expr>>> nextW = Collections.emptyMap(); for (int i = 0; i < trace.getActions().size(); ++i) { - final XcfaEdge edge = new XcfaEdge(trace.getAction(i).getSource(), trace.getAction(i).getTarget(), trace.getAction(i).getLabel()); + final XcfaEdge edge = new XcfaEdge(trace.getAction(i).getSource(), trace.getAction(i).getTarget(), trace.getAction(i).getLabel(), trace.getAction(i).getEdge().getMetadata()); final XcfaAction action = new XcfaAction(trace.getAction(i).getPid(), edge, nextW, trace.getAction(i).getInCnt()); sbeActions.add(action); nextW = action.nextWriteTriples(); From 94c67403d8c233b3ebc29a4dcd88650d4679b319 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:35:48 +0100 Subject: [PATCH 10/21] Not removing empty edges if they have non-empty metadata attached --- .../hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt index 90e7170707..5de0ad72ad 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt @@ -30,7 +30,8 @@ class EmptyEdgeRemovalPass : ProcedurePass { while (true) { val edge = builder.getEdges().find { it.label.isNop() && !it.target.error && !it.target.final && !it.source.initial && - (it.source.outgoingEdges.size == 1 || it.target.incomingEdges.size == 1) + (it.source.outgoingEdges.size == 1 || it.target.incomingEdges.size == 1) && + it.metadata is EmptyMetaData } ?: return builder val collapseBefore = edge.source.outgoingEdges.size == 1 builder.removeEdge(edge) @@ -55,5 +56,5 @@ class EmptyEdgeRemovalPass : ProcedurePass { is NopLabel -> true is StmtLabel -> stmt == Assume(True()) else -> false - } + }.and(metadata is EmptyMetaData) } \ No newline at end of file From 988391f737f34f79d00cc3da241185d8bcd3a04a Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:36:14 +0100 Subject: [PATCH 11/21] Adding metadata to error location pass --- .../hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt index d539cb6240..0e65bbfc97 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt @@ -32,10 +32,14 @@ class ErrorLocationPass(private val checkOverflow: Boolean) : ProcedurePass { (edges[0].label as SequenceLabel).labels[0]))) { builder.removeEdge(edge) edges.forEach { - if (predicate((it.label as SequenceLabel).labels[0])) { + val label = (it.label as SequenceLabel).labels[0] + if (predicate(label)) { if (builder.errorLoc.isEmpty) builder.createErrorLoc() builder.addEdge( - XcfaEdge(it.source, builder.errorLoc.get(), SequenceLabel(listOf()))) + XcfaEdge( + it.source, builder.errorLoc.get(), SequenceLabel(listOf()), metadata = label.metadata + ) + ) } else { builder.addEdge(it) } From c6ccac31c2c0e6e7afb74b3c3f8e9a0a4137838d Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 16:37:46 +0100 Subject: [PATCH 12/21] Added yml witness writing --- .../bme/mit/theta/xcfa/cli/ExecuteConfig.kt | 16 +- ...tnessWriter.kt => GraphmlWitnessWriter.kt} | 8 +- .../theta/xcfa/cli/utils/YmlWitnessWriter.kt | 195 ++++++++++++ .../theta/xcfa/cli/witnesses/CommonWitness.kt | 118 +++++++ .../xcfa/cli/witnesses/GraphmlWitness.kt | 207 ++++++++++++ .../mit/theta/xcfa/cli/witnesses/Witness.kt | 299 ------------------ .../theta/xcfa/cli/witnesses/YamlWitness.kt | 260 +++++++++++++++ .../bme/mit/theta/xcfa/cli/YamlParseTest.kt | 72 +++++ 8 files changed, 871 insertions(+), 304 deletions(-) rename subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/{XcfaWitnessWriter.kt => GraphmlWitnessWriter.kt} (96%) create mode 100644 subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt create mode 100644 subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt create mode 100644 subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt delete mode 100644 subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/Witness.kt create mode 100644 subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt create mode 100644 subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt index c7027914fc..f8987c875e 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt @@ -399,7 +399,7 @@ private fun postVerificationLogging( } } val witnessFile = File(resultFolder, "witness.graphml") - XcfaWitnessWriter() + GraphmlWitnessWriter() .writeWitness( safetyResult, config.inputConfig.input!!, @@ -410,6 +410,20 @@ private fun postVerificationLogging( parseContext, witnessFile, ) + val yamlWitnessFile = File(resultFolder, "witness.yml") + YmlWitnessWriter() + .writeWitness( + safetyResult, + config.inputConfig.input!!, + config.inputConfig.property, + (config.frontendConfig.specConfig as? CFrontendConfig)?.architecture, + getSolver( + config.outputConfig.witnessConfig.concretizerSolver, + config.outputConfig.witnessConfig.validateConcretizerSolver, + ), + parseContext, + yamlWitnessFile, + ) } } catch (e: Throwable) { logger.write(Logger.Level.INFO, "Could not output files: ${e.stackTraceToString()}\n") diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/XcfaWitnessWriter.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt similarity index 96% rename from subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/XcfaWitnessWriter.kt rename to subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt index 722fa7d91d..881a3202cf 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/XcfaWitnessWriter.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt @@ -23,7 +23,7 @@ import hu.bme.mit.theta.frontend.ParseContext import hu.bme.mit.theta.solver.SolverFactory import hu.bme.mit.theta.xcfa.analysis.XcfaAction import hu.bme.mit.theta.xcfa.analysis.XcfaState -import hu.bme.mit.theta.xcfa.cli.witnesses.Witness +import hu.bme.mit.theta.xcfa.cli.witnesses.GraphmlWitness import hu.bme.mit.theta.xcfa.cli.witnesses.XcfaTraceConcretizer import hu.bme.mit.theta.xcfa.cli.witnesses.traceToWitness import java.io.BufferedWriter @@ -34,7 +34,7 @@ import java.text.DateFormat import java.text.SimpleDateFormat import java.util.* -class XcfaWitnessWriter { +class GraphmlWitnessWriter { fun writeWitness( safetyResult: SafetyResult<*, *>, @@ -50,8 +50,8 @@ class XcfaWitnessWriter { parseContext) val witnessTrace = traceToWitness(trace = concrTrace, parseContext = parseContext) - val witness = Witness(witnessTrace, inputFile) - val xml = witness.toPrettyXml() + val graphmlWitness = GraphmlWitness(witnessTrace, inputFile) + val xml = graphmlWitness.toPrettyXml() witnessfile.writeText(xml) } else if (safetyResult.isSafe) { val taskHash = WitnessWriter.createTaskHash(inputFile.absolutePath) diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt new file mode 100644 index 0000000000..ae39115e9f --- /dev/null +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt @@ -0,0 +1,195 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package hu.bme.mit.theta.xcfa.cli.utils + +import hu.bme.mit.theta.analysis.Trace +import hu.bme.mit.theta.analysis.algorithm.Proof +import hu.bme.mit.theta.analysis.algorithm.SafetyResult +import hu.bme.mit.theta.analysis.algorithm.arg.ARG +import hu.bme.mit.theta.analysis.algorithm.arg.ArgNode +import hu.bme.mit.theta.analysis.expl.ExplState +import hu.bme.mit.theta.analysis.ptr.PtrState +import hu.bme.mit.theta.c2xcfa.CMetaData +import hu.bme.mit.theta.core.type.booltype.BoolExprs.Or +import hu.bme.mit.theta.core.utils.ExprUtils +import hu.bme.mit.theta.frontend.ParseContext +import hu.bme.mit.theta.frontend.transformation.ArchitectureConfig +import hu.bme.mit.theta.solver.SolverFactory +import hu.bme.mit.theta.xcfa.analysis.ErrorDetection +import hu.bme.mit.theta.xcfa.analysis.XcfaAction +import hu.bme.mit.theta.xcfa.analysis.XcfaState +import hu.bme.mit.theta.xcfa.cli.witnesses.* +import hu.bme.mit.theta.xcfa.model.MetaData +import hu.bme.mit.theta.xcfa.toC +import java.io.File +import java.util.* + + +class YmlWitnessWriter { + + fun writeWitness( + safetyResult: SafetyResult<*, *>, + inputFile: File, + property: ErrorDetection, + architecture: ArchitectureConfig.ArchitectureType?, + cexSolverFactory: SolverFactory, + parseContext: ParseContext, + witnessfile: File, + ) { + val metadata = Metadata( + formatVersion = "2.0", + uuid = UUID.randomUUID().toString(), + creationTime = getIsoDate(), + producer = Producer( + name = (System.getenv("VERIFIER_NAME")?:"").ifEmpty { "Theta" }, + version = (System.getenv("VERIFIER_VERSION")?:"").ifEmpty { "no version found" }, + ), + task = Task( + inputFiles = listOf(inputFile.name), + inputFileHashes = listOf(createTaskHash(inputFile.path)), + specification = property.name, + dataModel = architecture?.let { if(it == ArchitectureConfig.ArchitectureType.ILP32) DataModel.ILP32 else DataModel.LP64 } ?: DataModel.ILP32, + language = Language.C, + ) + ) + + if (safetyResult.isUnsafe && safetyResult.asUnsafe().cex is Trace<*, *>) { + val concrTrace: Trace, XcfaAction> = XcfaTraceConcretizer.concretize( + safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, cexSolverFactory, + parseContext) + + val witnessTrace = traceToWitness(trace = concrTrace, parseContext = parseContext) + + val witness = YamlWitness( + entryType = EntryType.VIOLATION, + metadata = metadata, + content = (0..(witnessTrace.length())).flatMap { + listOfNotNull( + witnessTrace.states.get(it)?.toSegment(witnessTrace.actions.getOrNull(it-1), inputFile), + witnessTrace.actions.getOrNull(it)?.toSegment(inputFile) + ) + } + ) + + witnessfile.writeText(WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness)) + } else if (safetyResult.isSafe) { + + val witness = YamlWitness( + entryType = EntryType.INVARIANTS, + metadata = metadata, + content = safetyResult.asSafe().proof.toContent(inputFile, parseContext) + ) + + witnessfile.writeText(WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness)) + } + } +} + +private fun getLocation(inputFile: File, metadata: MetaData?): Location? { + val line = (metadata as? CMetaData)?.lineNumberStart ?: (metadata as? CMetaData)?.lineNumberStop ?: return null + val column = (metadata as? CMetaData)?.colNumberStart ?: (metadata as? CMetaData)?.colNumberStop + return Location( + fileName = inputFile.name, + line = line, + column = column, + ) +} + +private fun getLocation(inputFile: File, witnessEdge: WitnessEdge?): Location? { + if(witnessEdge == null) return null + val endLoc = Location( + fileName = inputFile.name, + line = witnessEdge.endline ?: witnessEdge.startline ?: return null, + column = (witnessEdge.endcol ?: witnessEdge.startcol)?.plus(1), + ) + return endLoc +} + +private fun WitnessNode.toSegment(witnessEdge: WitnessEdge?, inputFile: File): ContentItem? { + if(violation) { + val loc = xcfaLocations.values.first().first() + val locLoc = getLocation(inputFile, loc.metadata) ?: getLocation(inputFile, witnessEdge) ?: getLocation(inputFile, witnessEdge?.edge?.metadata) ?: return null + return ContentItem(Segment( + Waypoint( + type = WaypointType.TARGET, + location = locLoc, + action = Action.FOLLOW + ) + )) + } else { + return null + } +} + +private fun WitnessEdge.toSegment(inputFile: File): ContentItem? { + val endLoc = Location( + fileName = inputFile.name, + line = endline ?: startline ?: return null, + column = (endcol ?: startcol)?.plus(1), + ) + val startLoc = Location( + fileName = inputFile.name, + line = startline ?: endline ?: return null, + column = (startcol ?: endcol)?.plus(1), + ) + + val (loc, constraint, type) = if(assumption != null) { + Triple(endLoc, Constraint(value = assumption, format = Format.C_EXPRESSION), WaypointType.ASSUMPTION) + } else if(control != null) { + Triple(startLoc, Constraint(value = control.toString()), WaypointType.BRANCHING) + } else if(enterLoopHead) { + Triple(startLoc, Constraint(value = "true"), WaypointType.BRANCHING) + } else if(enterFunction != null) { + Triple(startLoc, Constraint(value = enterFunction), WaypointType.FUNCTION_ENTER) + } else if(returnFromFunction != null) { + Triple(endLoc, Constraint(value = returnFromFunction), WaypointType.FUNCTION_RETURN) + } else return null + return ContentItem(Segment( + Waypoint( + type = type, + constraint = constraint, + location = loc, + action = Action.FOLLOW + ) + )) +} + +private fun Proof.toContent(inputFile: File, parseContext: ParseContext): List { + if(this is ARG<*, *>) { + val locMap = nodes.toList().mapNotNull { + it as ArgNode, XcfaAction> + val loc = it.state.processes.values.firstOrNull()?.locs?.peek() ?: return@mapNotNull null + val locLoc = Location( + fileName = inputFile.name, + line = (loc.metadata as? CMetaData)?.lineNumberStart ?: (loc.metadata as? CMetaData)?.lineNumberStop ?: return@mapNotNull null, + column = (loc.metadata as? CMetaData)?.colNumberStart ?: (loc.metadata as? CMetaData)?.colNumberStop, + ) + locLoc to it.state.sGlobal.toExpr() + }.groupBy{ it.first } + val invs = locMap.mapValues { entry -> ExprUtils.simplify(Or(entry.value.map { it.second })) }.map { + ContentItem( + invariant = Invariant( + type = InvariantType.LOCATION_INVARIANT, + location = it.key, + value = it.value.toC(parseContext), + format = Format.C_EXPRESSION + ) + ) + } + return invs + } + return listOf() +} \ No newline at end of file diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt new file mode 100644 index 0000000000..fcaf982dfb --- /dev/null +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package hu.bme.mit.theta.xcfa.cli.witnesses + +import hu.bme.mit.theta.analysis.Action +import hu.bme.mit.theta.analysis.State +import hu.bme.mit.theta.analysis.expl.ExplState +import hu.bme.mit.theta.xcfa.model.XcfaEdge +import hu.bme.mit.theta.xcfa.model.XcfaLocation +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Paths +import java.security.DigestInputStream +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.* + +data class WitnessNode( + val id: String, + val entry: Boolean = false, + val sink: Boolean = false, + val violation: Boolean = false, + + val xcfaLocations: Map> = emptyMap(), + val cSources: Map> = emptyMap(), + val globalState: ExplState? = null +) : State { + + override fun isBottom(): Boolean { + error("Not applicable for witness states.") + } +} + +data class WitnessEdge( + val sourceId: String, + val targetId: String, + val assumption: String? = null, + val assumption_scope: String? = null, + val assumption_resultfunction: String? = null, + val control: Boolean? = null, + val startline: Int? = null, + val endline: Int? = null, + val startoffset: Int? = null, + val endoffset: Int? = null, + val startcol: Int? = null, + val endcol: Int? = null, + val enterLoopHead: Boolean = false, + val enterFunction: String? = null, + val returnFromFunction: String? = null, + val threadId: String? = null, + val createThread: String? = null, + + val stmt: String? = null, + val cSource: String? = null, + val edge: XcfaEdge? = null, +) : Action { +} + +fun createTaskHash(programFile: String): String { + var md: MessageDigest? = null + try { + md = MessageDigest.getInstance("SHA-256") + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } + try { + Files.newInputStream(Paths.get(programFile)).use { `is` -> + DigestInputStream(`is`, md).use { dis -> + while (dis.read() != -1) { + } + } + } + } catch (e: IOException) { + e.printStackTrace() + } + assert(md != null) + val digest = md!!.digest() + return bytesToHex(digest) +} + +// source: https://www.baeldung.com/sha-256-hashing-java +fun bytesToHex(hash: ByteArray): String { + val hexString = StringBuilder(2 * hash.size) + for (i in hash.indices) { + val hex = Integer.toHexString(0xff and hash[i].toInt()) + if (hex.length == 1) { + hexString.append('0') + } + hexString.append(hex) + } + return hexString.toString() +} + +fun getIsoDate(): String { + val tz: TimeZone = TimeZone.getTimeZone("UTC") + val df: DateFormat = SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'" + ) // Quoted "Z" to indicate UTC, no timezone offset + + df.timeZone = tz + return df.format(Date()) +} \ No newline at end of file diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt new file mode 100644 index 0000000000..d2906d7359 --- /dev/null +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package hu.bme.mit.theta.xcfa.cli.witnesses + +import hu.bme.mit.theta.analysis.Trace +import java.io.File +import java.io.StringReader +import java.io.StringWriter +import javax.xml.XMLConstants +import javax.xml.transform.OutputKeys +import javax.xml.transform.Source +import javax.xml.transform.Transformer +import javax.xml.transform.TransformerFactory +import javax.xml.transform.stream.StreamResult +import javax.xml.transform.stream.StreamSource + + +class GraphmlWitness(private val trace: Trace, programFile: File) { + + private val attributes: MutableList = ArrayList() + private val data: MutableList> = ArrayList() + + init { + attributes.add(GraphmlWitnessAttribute("sourcecodelang", "string", "graph", "sourcecodelang")) + attributes.add(GraphmlWitnessAttribute("creationtime", "string", "graph", "creationtime")) + attributes.add(GraphmlWitnessAttribute("witness-type", "string", "graph", "witness-type")) + attributes.add(GraphmlWitnessAttribute("producer", "string", "graph", "producer")) + attributes.add(GraphmlWitnessAttribute("architecture", "string", "graph", "architecture")) + attributes.add(GraphmlWitnessAttribute("programHash", "string", "graph", "programhash")) + attributes.add(GraphmlWitnessAttribute("programfile", "string", "graph", "programfile")) + attributes.add(GraphmlWitnessAttribute("specification", "string", "graph", "specification")) + + attributes.add(GraphmlWitnessAttribute("assumption", "string", "edge", "assumption")) + attributes.add(GraphmlWitnessAttribute("assumption.scope", "string", "edge", "assumption.scope")) + attributes.add( + GraphmlWitnessAttribute( + "assumption.resultfunction", "string", "edge", + "assumption.resultfunction")) + attributes.add(GraphmlWitnessAttribute("control", "string", "edge", "control")) + attributes.add(GraphmlWitnessAttribute("startline", "string", "edge", "startline")) + attributes.add(GraphmlWitnessAttribute("endline", "string", "edge", "endline")) + attributes.add(GraphmlWitnessAttribute("startoffset", "string", "edge", "startoffset")) + attributes.add(GraphmlWitnessAttribute("endoffset", "string", "edge", "endoffset")) + attributes.add(GraphmlWitnessAttribute("enterLoopHead", "string", "edge", "enterLoopHead")) + attributes.add(GraphmlWitnessAttribute("enterFunction", "string", "edge", "enterFunction")) + attributes.add( + GraphmlWitnessAttribute("returnFromFunction", "string", "edge", "returnFromFunction") + ) + attributes.add(GraphmlWitnessAttribute("threadId", "string", "edge", "threadId")) + attributes.add(GraphmlWitnessAttribute("createThread", "string", "edge", "createThread")) + attributes.add(GraphmlWitnessAttribute("stmt", "string", "edge", "stmt")) + attributes.add(GraphmlWitnessAttribute("cSource", "string", "edge", "cSource")) + + attributes.add(GraphmlWitnessAttribute("entry", "string", "node", "entry", "false")) + attributes.add(GraphmlWitnessAttribute("sink", "string", "node", "sink", "false")) + attributes.add(GraphmlWitnessAttribute("violation", "string", "node", "violation", "false")) + attributes.add(GraphmlWitnessAttribute("locationStacks", "string", "node", "locationStacks")) + attributes.add(GraphmlWitnessAttribute("sourceLines", "string", "node", "sourceLines")) + attributes.add(GraphmlWitnessAttribute("state", "string", "node", "state")) + + data.add(Pair("witness-type", "violation_witness")) + data.add(Pair("producer", "theta")) + data.add(Pair("sourcecodelang", "C")) + data.add(Pair("specification", "CHECK( init(main()), LTL(G ! call(reach_error())) )")) + data.add(Pair("programfile", programFile.absolutePath)) + data.add(Pair("programhash", createTaskHash(programFile.path))) + data.add(Pair("architecture", "32bit")) + data.add(Pair("creationtime", getIsoDate())) + } + + fun toPrettyXml(): String = prettyFormat(toXml(), 4) + + fun toXml(): String = """ + + + +${attributes.map(GraphmlWitnessAttribute::toXml).reduce { a, b -> "$a\n$b" }} + + + +${data.map { "${it.second}" }.reduce { a, b -> "$a\n$b" }} + +${trace.states.map(WitnessNode::toXml).reduce { a, b -> "$a\n$b" }} + +${trace.actions.map(WitnessEdge::toXml).reduce { a, b -> "$a\n$b" }} + + + + """.trimIndent() + +} + +data class GraphmlWitnessAttribute( + val name: String, + val type: String, + val `for`: String, + val id: String, + val defaultValue: String? = null +) { + + fun toXml(): String = """ +" else """ +> +$defaultValue + +""".trimIndent() + } +""".trimIndent() +} + +private fun escapeXml(toEscape: String): String { + var toEscape = toEscape + toEscape = toEscape.replace("&", "&") + toEscape = toEscape.replace("\"", """) + toEscape = toEscape.replace("'", "'") + toEscape = toEscape.replace("<", "<") + toEscape = toEscape.replace(">", ">") + return toEscape +} + +// from https://stackoverflow.com/a/1264912 +private fun prettyFormat(input: String, indent: Int): String { + return try { + val xmlInput: Source = StreamSource( + StringReader(input.replace(Regex("( )|[\\t\\n\\r]"), ""))) + val stringWriter = StringWriter() + val xmlOutput = StreamResult(stringWriter) + val transformerFactory: TransformerFactory = TransformerFactory.newInstance() + transformerFactory.setAttribute("indent-number", indent) + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "") + val transformer: Transformer = transformerFactory.newTransformer() + transformer.setOutputProperty(OutputKeys.INDENT, "yes") + transformer.transform(xmlInput, xmlOutput) + xmlOutput.getWriter().toString() + } catch (e: Exception) { + System.err.println(input.replace(Regex("( )|[\\t\\n\\r]"), "")) + throw RuntimeException(e) + } +} + +fun WitnessNode.toXml(): String = """ + + ${if (entry) "true" else ""} + ${if (sink) "true" else ""} + ${if (violation) "true" else ""} + + ${ + if (xcfaLocations.isNotEmpty()) "${ + escapeXml(xcfaLocations.toString()) + }" else "" +} + ${ + if (cSources.isNotEmpty()) "${ + escapeXml(cSources.toString()) + }" else "" +} + ${ + if (globalState != null) "${ + escapeXml(globalState.toString()) + }" else "" +} + + """.trimIndent() + +fun WitnessEdge.toXml(): String = """ + + ${if (assumption != null) "$assumption" else ""} + ${if (assumption_scope != null) "$assumption_scope" else ""} + ${if (assumption_resultfunction != null) "$assumption_resultfunction" else ""} + ${if (control != null) "condition-$control" else ""} + ${if (startline != null && startline != -1) "$startline" else ""} + ${if (endline != null && endline != -1) "$endline" else ""} + ${if (startoffset != null && startoffset != -1) "$startoffset" else ""} + ${if (endoffset != null && endoffset != -1) "$endoffset" else ""} + ${if (enterLoopHead) "true" else ""} + ${if (enterFunction != null) "$enterFunction" else ""} + ${if (returnFromFunction != null) "$returnFromFunction" else ""} + ${if (threadId != null) "$threadId" else ""} + ${if (createThread != null) "$createThread" else ""} + + ${if (stmt != null) "${escapeXml(stmt)}" else ""} + ${ + if (cSource != null && cSource != "") "${ + escapeXml(cSource) + }" else "" +} + + + """.trimIndent() \ No newline at end of file diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/Witness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/Witness.kt deleted file mode 100644 index 4569a1b557..0000000000 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/Witness.kt +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2024 Budapest University of Technology and Economics - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package hu.bme.mit.theta.xcfa.cli.witnesses - -import hu.bme.mit.theta.analysis.Action -import hu.bme.mit.theta.analysis.State -import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.expl.ExplState -import hu.bme.mit.theta.xcfa.model.XcfaLocation -import java.io.File -import java.io.IOException -import java.io.StringReader -import java.io.StringWriter -import java.nio.file.Files -import java.nio.file.Paths -import java.security.DigestInputStream -import java.security.MessageDigest -import java.security.NoSuchAlgorithmException -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.* -import javax.xml.XMLConstants -import javax.xml.transform.OutputKeys -import javax.xml.transform.Source -import javax.xml.transform.Transformer -import javax.xml.transform.TransformerFactory -import javax.xml.transform.stream.StreamResult -import javax.xml.transform.stream.StreamSource - - -class Witness(private val trace: Trace, programFile: File) { - - private val attributes: MutableList = ArrayList() - private val data: MutableList> = ArrayList() - - init { - attributes.add(WitnessAttribute("sourcecodelang", "string", "graph", "sourcecodelang")) - attributes.add(WitnessAttribute("creationtime", "string", "graph", "creationtime")) - attributes.add(WitnessAttribute("witness-type", "string", "graph", "witness-type")) - attributes.add(WitnessAttribute("producer", "string", "graph", "producer")) - attributes.add(WitnessAttribute("architecture", "string", "graph", "architecture")) - attributes.add(WitnessAttribute("programHash", "string", "graph", "programhash")) - attributes.add(WitnessAttribute("programfile", "string", "graph", "programfile")) - attributes.add(WitnessAttribute("specification", "string", "graph", "specification")) - - attributes.add(WitnessAttribute("assumption", "string", "edge", "assumption")) - attributes.add(WitnessAttribute("assumption.scope", "string", "edge", "assumption.scope")) - attributes.add(WitnessAttribute("assumption.resultfunction", "string", "edge", - "assumption.resultfunction")) - attributes.add(WitnessAttribute("control", "string", "edge", "control")) - attributes.add(WitnessAttribute("startline", "string", "edge", "startline")) - attributes.add(WitnessAttribute("endline", "string", "edge", "endline")) - attributes.add(WitnessAttribute("startoffset", "string", "edge", "startoffset")) - attributes.add(WitnessAttribute("endoffset", "string", "edge", "endoffset")) - attributes.add(WitnessAttribute("enterLoopHead", "string", "edge", "enterLoopHead")) - attributes.add(WitnessAttribute("enterFunction", "string", "edge", "enterFunction")) - attributes.add( - WitnessAttribute("returnFromFunction", "string", "edge", "returnFromFunction")) - attributes.add(WitnessAttribute("threadId", "string", "edge", "threadId")) - attributes.add(WitnessAttribute("createThread", "string", "edge", "createThread")) - attributes.add(WitnessAttribute("stmt", "string", "edge", "stmt")) - attributes.add(WitnessAttribute("cSource", "string", "edge", "cSource")) - - attributes.add(WitnessAttribute("entry", "string", "node", "entry", "false")) - attributes.add(WitnessAttribute("sink", "string", "node", "sink", "false")) - attributes.add(WitnessAttribute("violation", "string", "node", "violation", "false")) - attributes.add(WitnessAttribute("locationStacks", "string", "node", "locationStacks")) - attributes.add(WitnessAttribute("sourceLines", "string", "node", "sourceLines")) - attributes.add(WitnessAttribute("state", "string", "node", "state")) - - data.add(Pair("witness-type", "violation_witness")) - data.add(Pair("producer", "theta")) - data.add(Pair("sourcecodelang", "C")) - data.add(Pair("specification", "CHECK( init(main()), LTL(G ! call(reach_error())) )")) - data.add(Pair("programfile", programFile.absolutePath)) - data.add(Pair("programhash", createTaskHash(programFile.path))) - data.add(Pair("architecture", "32bit")) - data.add(Pair("creationtime", getIsoDate())) - } - - fun toPrettyXml(): String = prettyFormat(toXml(), 4) - - fun toXml(): String = """ - - - -${attributes.map(WitnessAttribute::toXml).reduce { a, b -> "$a\n$b" }} - - - -${data.map { "${it.second}" }.reduce { a, b -> "$a\n$b" }} - -${trace.states.map(WitnessNode::toXml).reduce { a, b -> "$a\n$b" }} - -${trace.actions.map(WitnessEdge::toXml).reduce { a, b -> "$a\n$b" }} - - - - """.trimIndent() - -} - -data class WitnessAttribute( - val name: String, - val type: String, - val `for`: String, - val id: String, - val defaultValue: String? = null -) { - - fun toXml(): String = """ -" else """ -> -$defaultValue - -""".trimIndent() - } -""".trimIndent() -} - -data class WitnessNode( - val id: String, - val entry: Boolean = false, - val sink: Boolean = false, - val violation: Boolean = false, - - val xcfaLocations: Map> = emptyMap(), - val cSources: Map> = emptyMap(), - val globalState: ExplState? = null -) : State { - - override fun isBottom(): Boolean { - error("Not applicable for witness states.") - } - - fun toXml(): String = """ - - ${if (entry) "true" else ""} - ${if (sink) "true" else ""} - ${if (violation) "true" else ""} - - ${ - if (xcfaLocations.isNotEmpty()) "${ - escapeXml(xcfaLocations.toString()) - }" else "" - } - ${ - if (cSources.isNotEmpty()) "${ - escapeXml(cSources.toString()) - }" else "" - } - ${ - if (globalState != null) "${ - escapeXml(globalState.toString()) - }" else "" - } - - """.trimIndent() -} - -data class WitnessEdge( - val sourceId: String, - val targetId: String, - val assumption: String? = null, - val assumption_scope: String? = null, - val assumption_resultfunction: String? = null, - val control: Boolean? = null, - val startline: Int? = null, - val endline: Int? = null, - val startoffset: Int? = null, - val endoffset: Int? = null, - val enterLoopHead: Boolean = false, - val enterFunction: String? = null, - val returnFromFunction: String? = null, - val threadId: String? = null, - val createThread: String? = null, - - val stmt: String? = null, - val cSource: String? = null, -) : Action { - - fun toXml(): String = """ - - ${if (assumption != null) "$assumption" else ""} - ${if (assumption_scope != null) "$assumption_scope" else ""} - ${if (assumption_resultfunction != null) "$assumption_resultfunction" else ""} - ${if (control != null) "condition-$control" else ""} - ${if (startline != null && startline != -1) "$startline" else ""} - ${if (endline != null && endline != -1) "$endline" else ""} - ${if (startoffset != null && startoffset != -1) "$startoffset" else ""} - ${if (endoffset != null && endoffset != -1) "$endoffset" else ""} - ${if (enterLoopHead) "true" else ""} - ${if (enterFunction != null) "$enterFunction" else ""} - ${if (returnFromFunction != null) "$returnFromFunction" else ""} - ${if (threadId != null) "$threadId" else ""} - ${if (createThread != null) "$createThread" else ""} - - ${if (stmt != null) "${escapeXml(stmt)}" else ""} - ${ - if (cSource != null && cSource != "") "${ - escapeXml(cSource) - }" else "" - } - - - """.trimIndent() -} - -private fun escapeXml(toEscape: String): String { - var toEscape = toEscape - toEscape = toEscape.replace("&", "&") - toEscape = toEscape.replace("\"", """) - toEscape = toEscape.replace("'", "'") - toEscape = toEscape.replace("<", "<") - toEscape = toEscape.replace(">", ">") - return toEscape -} - -private fun createTaskHash(programFile: String): String { - var md: MessageDigest? = null - try { - md = MessageDigest.getInstance("SHA-256") - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - } - try { - Files.newInputStream(Paths.get(programFile)).use { `is` -> - DigestInputStream(`is`, md).use { dis -> - while (dis.read() != -1) { - } - } - } - } catch (e: IOException) { - e.printStackTrace() - } - assert(md != null) - val digest = md!!.digest() - return bytesToHex(digest) -} - -// source: https://www.baeldung.com/sha-256-hashing-java -private fun bytesToHex(hash: ByteArray): String { - val hexString = StringBuilder(2 * hash.size) - for (i in hash.indices) { - val hex = Integer.toHexString(0xff and hash[i].toInt()) - if (hex.length == 1) { - hexString.append('0') - } - hexString.append(hex) - } - return hexString.toString() -} - -private fun getIsoDate(): String { - val tz: TimeZone = TimeZone.getTimeZone("UTC") - val df: DateFormat = SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss'Z'") // Quoted "Z" to indicate UTC, no timezone offset - - df.timeZone = tz - return df.format(Date()) -} - -// from https://stackoverflow.com/a/1264912 -private fun prettyFormat(input: String, indent: Int): String { - return try { - val xmlInput: Source = StreamSource( - StringReader(input.replace(Regex("( )|[\\t\\n\\r]"), ""))) - val stringWriter = StringWriter() - val xmlOutput = StreamResult(stringWriter) - val transformerFactory: TransformerFactory = TransformerFactory.newInstance() - transformerFactory.setAttribute("indent-number", indent) - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "") - val transformer: Transformer = transformerFactory.newTransformer() - transformer.setOutputProperty(OutputKeys.INDENT, "yes") - transformer.transform(xmlInput, xmlOutput) - xmlOutput.getWriter().toString() - } catch (e: Exception) { - System.err.println(input.replace(Regex("( )|[\\t\\n\\r]"), "")) - throw RuntimeException(e) - } -} \ No newline at end of file diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt new file mode 100644 index 0000000000..b3c000f5ad --- /dev/null +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt @@ -0,0 +1,260 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package hu.bme.mit.theta.xcfa.cli.witnesses + +import com.charleskorn.kaml.Yaml +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +val WitnessYamlConfig = Yaml(configuration = Yaml.default.configuration.copy(encodeDefaults = false)) + +// https://gitlab.com/sosy-lab/benchmarking/sv-witnesses/-/blob/8f5dc4bf00c01bc6d5636d7993e164d181e19204/violation-witness-schema.yml +// https://gitlab.com/sosy-lab/benchmarking/sv-witnesses/-/blob/8f5dc4bf00c01bc6d5636d7993e164d181e19204/correctness-witness-schema.yml + +/** + * For violations: + * Each entry consists of three key-value pairs, namely the key `entry_type` with value `violation_sequence`, + * the key metadata, and the key content. + * For correctness: + * The `entry_type` defines what content is available in the content field. The only allowed entry type for a correctness witness is `invariant_set`. + * @param entryType The `entry_type` defines what content is available in the content field. The only allowed entry type for a correctness witness is `violation_sequence`. + * @param metadata The meta data describe the provenance of the data. + * @param content For violations: The content represents the semantical content of the violation witness. It is a sequence of one or more segments. The content contains a sequence of zero or more normal segments and exactly one final segment at the end. + * For correctness: The content represents the semantical content of the correctness witness. It is a sequence of one or more invariant elements. + * + */ +@Serializable data class YamlWitness( + @SerialName("entry_type") + val entryType: EntryType, + val metadata: Metadata, + val content: List, +) + +@Serializable enum class EntryType { + @SerialName("violation_sequence") VIOLATION, + @SerialName("invariant_set") INVARIANTS, +} + +/** + * The meta data describe the provenance of the data. + * @param formatVersion The `version` of the format is given as a string (currently "2.0"). + * @param uuid The `uuid` is a unique identifier of the entry; it uses the UUID format defined in RFC4122. + * @param creationTime The `creation_time` describes the date and time when the entry was created; it uses the format given by ISO 8601. + * @param producer The key `producer` describes the tool that produced the entry. + * + */ +@Serializable data class Metadata( + @SerialName("format_version") + val formatVersion: String, + val uuid: String, + @SerialName("creation_time") + val creationTime: String, + val producer: Producer, + val task: Task, +) + +/** + * The key `producer` describes the tool that produced the entry. + * @param name The name of the tool that produced the witness. + * @param version The version of the tool + * @param configuration The configuration in which the tool ran (optional) + * @param commandLine The command line with which the tool ran; it should be a bash-compliant command (optional) + * @param description Any information not fitting in the previous items (optional) + */ +@Serializable data class Producer( + val name: String, + val version: String, + val configuration: String? = null, + @SerialName("command_line") + val commandLine: String? = null, + val description: String? = null, +) + +/** + * The task describes the verification task to which the entry is related. + * @param inputFiles The list of files given as input to the verifier, e.g. ["path/f1.c", "path/f2.c"]. + * @param inputFileHashes The SHA-256 hashes of all files in input_files, e.g. {"path/f1.c": 511..., "path/f2.c": f70...} + * @param specification The specification considered by the verifier; it uses the SV-COMP format given at https://sv-comp.sosy-lab.org/2023/rules.php. + * @param dataModel The data model assumed for the input program. (ILP32 / LP64) + * @param language The programming language of the input files; the format currently supports only C. + */ +@Serializable data class Task( + @SerialName("input_files") + val inputFiles: List, + @SerialName("input_file_hashes") + val inputFileHashes: List, + val specification: String, + @SerialName("data_model") + val dataModel: DataModel, + val language: Language, +) + +@Serializable enum class DataModel { + ILP32, + LP64, +} + +@Serializable enum class Language { + C +} + +/** + * @param segment A `segment` is a sequence of one or more waypoints. They are used to structure the waypoints into segments. Each `segment` is a sequence of zero or more waypoints with action `avoid` and exactly one waypoint of action `follow` at the end. A segment is called _final_ if it ends with the `target` waypoint and it is called _normal_ otherwise. items: type: object required: - waypoint properties: waypoint: type: object required: - type - action - location description: | The `waypoint` elements are the basic building block of violation witnesses. They have the form of simple restrictions on program executions. Technically, a waypoint is a mapping with four keys, namely type, location, constraint, and action. The values of the first three keys specify the requirement on a program execution to pass a waypoint: `type` describes the type of the requirement, `location` specifies the program location where the requirement is evaluated, and `constraint` gives the requirement itself and is not allowed for waypoints of type `function_enter` and `target`. The key `action` then states whether the executions represented by the witness should pass through the waypoint (value `follow`) or avoid it (value `avoid`). The format currently supports two possible values of type with the following meanings: - `assumption`: The location has to point to the beginning of a statement or a declaration inside a compound statement. A requirement of this type says that a given constraint is satisfied before the pointed statement or declaration inside a compound statement. The constraint is a mapping with two keys: `format` specifies the language of the assumption and `value` contains a side-effect-free assumption over variables in the current scope. The value of `format` is `c_expression` as C expressions are the only assumptions currently supported. In future, we plan to support also assumptions in ACSL. - `target`: This type of requirement can be used only with action `follow` and it marks the program location where the property is violated. More precisely, the location points at the first character of the statement or full expression whose evaluation is sequenced directly before the violation occurs, i.e., there is no other evaluation sequenced before the violation and the sequence point associated with the location. This also implies that it can only point to a function call if it calls a function of the C standard library + * @param invariant The key `invariant` is the basic building block of correctness witnesses. It is a mapping that describes one invariant. + */ +@Serializable data class ContentItem( + val segment: Segment? = null, + val invariant: Invariant? = null, +) + +@Serializable data class Segment( + val waypoint: Waypoint, +) + +/** + * The `waypoint` elements are the basic building block of violation witnesses. + * They have the form of simple restrictions on program executions. + * Technically, a waypoint is a mapping with four keys, namely type, location, constraint, and action. + * The values of the first three keys specify the requirement on a program execution to pass a waypoint: + * `type` describes the type of the requirement, + * `location` specifies the program location where the requirement is evaluated, and + * `constraint` gives the requirement itself and is not allowed for waypoints of type `function_enter` and `target`. + * The key `action` then states whether the executions represented by the witness should + * pass through the waypoint (value `follow`) or avoid it (value `avoid`). + * The format currently supports two possible values of type with the following meanings: + * + * - `assumption`: + * The location has to point to the beginning of a statement or a declaration inside a compound statement. + * A requirement of this type says that a given constraint is satisfied before the pointed statement + * or declaration inside a compound statement. + * The constraint is a mapping with two keys: `format` specifies the language of the assumption and + * `value` contains a side-effect-free assumption over variables in the current scope. + * The value of `format` is `c_expression` as C expressions are the only assumptions currently supported. + * In future, we plan to support also assumptions in ACSL. + * - `target`: + * This type of requirement can be used only with action `follow` and it marks the program location where the property is violated. + * More precisely, the location points at the first character of the statement or + * full expression whose evaluation is sequenced directly before the violation occurs, + * i.e., there is no other evaluation sequenced before the violation and the sequence point associated with the location. + * This also implies that it can only point to a function call if it calls a function of the C standard library + * that violates the property or if the function call itself is the property violation. + * The key constraint has to be omitted for type `target`. + * - `function_enter`: + * The location points to the right parenthesis after the function arguments at the call site and the requirement + * says that the called function is entered. The key constraint has to be omitted in this case. + * - `function_return`: + * Such a requirement says that a given function call has been evaluated and the returned + * value satisfies a given constraint. The location points to the right parenthesis after the + * function arguments at the call site. The constraint is a mapping with keys format and value. + * We currently support only ACSL expressions of the form `\result `, + * where `` is one of `==`, `!=`, `<=`, `<`, `>`, `>=` and `` is a constant expression. + * The value of format has to be `acsl_expression`. + * - `branching`: + * A requirement of this type says that a given branching is evaluated in a given way. + * The location points to a branching keyword like `if`, `while`, `switch`, or to the character `?` + * in the ternary operator (`?:`). The constraint is then a mapping with only one key value. + * For binary branchings, value can be either `true` or `false` saying whether the true branch + * is used or not. For the keyword switch, value holds an integer constant or default. The + * integer constant specifies the value of the controlling expression of the switch statement. + * The value default says that the value of this expression does not match any case of the + * switch with the potential exception of the default case. + * + * An `assumption` waypoint is evaluated at the sequence point + * immediately before the waypoint location. The waypoint is passed if + * the given constraint evaluates to true. A `branching` waypoint + * is evaluated at the sequence point immediately after evaluation of the + * controlling expression of the corresponding branching statement. The + * waypoint is passed if the resulting value of the controlling + * expression corresponds to the given constraint. A + * `function_enter` waypoint is evaluated at the sequence point + * immediately after evaluation of all arguments of the function + * call. The waypoint is passed without any additional constraint. A + * `function_return` waypoint is evaluated immediately after + * evaluation of the corresponding function call. The waypoint is passed + * if the returned value satisfies the given constraint. + * + * @param type + * @param constraint The constraint of the waypoint. A constraint is not allowed for type `target`. + * @param location The `location` is a mapping with mandatory keys file_name and line. All other keys are optional. If the location provides an inconsistent information (e.g., identifier specifies a function that is not called at the given column on the given line ), the witness is syntactically invalid. + * @param action Action `follow` means that the waypoint should be passed through. Action `avoid` means that the waypoint should be avoided. + */ + +@Serializable data class Waypoint( + val type: WaypointType, + val constraint: Constraint? = null, + val location: Location, + val action: Action, +) + +@Serializable enum class WaypointType { + @SerialName("assumption") ASSUMPTION, + @SerialName("target") TARGET, + @SerialName("function_enter") FUNCTION_ENTER, + @SerialName("function_return") FUNCTION_RETURN, + @SerialName("branching") BRANCHING, +} + +/** + * The constraint of the waypoint. A constraint is not allowed for type `target`. + * @param value + * @param format + */ +@Serializable data class Constraint( + val value: String, + val format: Format? = null, +) + +@Serializable enum class Format { + @SerialName("c_expression") C_EXPRESSION, + @SerialName("acsl_expression") ACSL_EXPRESSION, +} + +/** + * The `location` is a mapping with mandatory keys file_name and line. All other keys are optional. If the location provides an inconsistent information (e.g., identifier specifies a function that is not called at the given column on the given line ), the witness is syntactically invalid. + * @param fileName The name of the file of the location + * @param line The line number pf the program location in the file. + * @param column The key `column` specifies the column number of the location, i.e., the position of the `column`-th character in the line that the location points to (value 1 is the position of the first character). If the column is not given, then it is interpreted as the leftmost suitable position on the line, where suitability is given by `type`. + * @param function The key `function` gives the name of the function containing the location. It is usually determined by the `file_name` and `line`, but the information can improve human readability of the witness. + */ +@Serializable data class Location( + @SerialName("file_name") + val fileName: String, + val line: Int, + val column: Int? = null, + val function: String? = null, +) + +/** + * Action `follow` means that the waypoint should be passed through. + * Action `avoid` means that the waypoint should be avoided. + */ +@Serializable enum class Action { + @SerialName("follow") FOLLOW, + @SerialName("avoid") AVOID, +} + +@Serializable data class Invariant( + val type: InvariantType, + val location: Location, + val value: String, + val format: Format, +) + +@Serializable enum class InvariantType { + @SerialName("loop_invariant") LOOP_INVARIANT, + @SerialName("location_invariant") LOCATION_INVARIANT, +} \ No newline at end of file diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt new file mode 100644 index 0000000000..f157011728 --- /dev/null +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2024 Budapest University of Technology and Economics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package hu.bme.mit.theta.xcfa.cli + +import com.charleskorn.kaml.Yaml +import hu.bme.mit.theta.xcfa.cli.witnesses.* +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import java.util.* + +class YamlParseTest { + @Test + fun serialize() { + val witness = YamlWitness( + entryType = EntryType.VIOLATION, + metadata = Metadata( + formatVersion = "2.0", + uuid = UUID.randomUUID().toString(), + creationTime = getIsoDate(), + producer = Producer( + name = "test", + version = "1.0.0", + ), + task = Task( + inputFiles = listOf("example.c"), + inputFileHashes = listOf("hash"), + specification = "unreach_call", + dataModel = DataModel.LP64, + language = Language.C, + ) + ), + content = listOf( + ContentItem( + Segment(Waypoint( + type = WaypointType.ASSUMPTION, + constraint = Constraint( + value = "1 < x", + format = Format.C_EXPRESSION, + ), + location = Location( + fileName = "example.c", + line = 15, + ), + action = Action.FOLLOW, + )) + ), + ), + ) + + val result = WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness) + + System.err.println(result) + + val parsedPack = Yaml.default.decodeFromString(YamlWitness.serializer(), result) + + Assertions.assertEquals(witness, parsedPack) + } +} \ No newline at end of file From 3ab5dee0da50a7fc3a9b463c9fa1ad0e9b28c4b6 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:13:30 +0100 Subject: [PATCH 13/21] Adapted XcfaLocation serialization, as well as XcfaEdge and XcfaLoation metadata --- .gitignore | 1 + .../frontend/chc/ChcBackwardXcfaBuilder.java | 14 +- .../frontend/chc/ChcForwardXcfaBuilder.java | 20 +- .../java/hu/bme/mit/theta/c2xcfa/CMetaData.kt | 41 +- .../mit/theta/c2xcfa/FrontendXcfaBuilder.kt | 1 - .../litmus2xcfa/dsl/LitmusAArch64.java | 18 +- .../bme/mit/theta/llvm2xcfa/LlvmMetadata.java | 7 + .../hu/bme/mit/theta/llvm2xcfa/Utils.java | 2 +- .../concrete/ArrayIntrinsicsHandler.java | 2 +- .../concrete/MemoryInstructionHandler.java | 2 +- .../concrete/OtherInstructionHandler.java | 17 +- .../handlers/states/FunctionState.java | 2 +- .../mit/theta/xcfa/analysis/XcfaAnalysis.kt | 2 + .../xcfa/analysis/XcfaExplAnalysisTest.kt | 8 +- .../xcfa/analysis/XcfaPredAnalysisTest.kt | 8 +- .../theta/xcfa/analysis/XcfaStateLtsTest.kt | 10 +- .../bme/mit/theta/xcfa/cli/ExecuteConfig.kt | 6 +- .../bme/mit/theta/xcfa/cli/utils/GsonUtils.kt | 5 +- .../mit/theta/xcfa/cli/XcfaCliParseTest.kt | 1 + .../mit/theta/xcfa/cli/XcfaCliProofTest.kt | 16 +- .../test/resources/json/00assignment.c.json | 200 +- .../src/test/resources/json/01cast.c.json | 230 +- .../src/test/resources/json/02types.c.json | 330 +- .../src/test/resources/json/03bitwise.c.json | 236 +- .../src/test/resources/json/04real.c.json | 230 +- .../src/test/resources/json/05math.c.json | 350 +- .../src/test/resources/json/06arrays.c.json | 270 +- .../test/resources/json/07arrayinit.c.json | 288 +- .../src/test/resources/json/08vararray.c.json | 288 +- .../src/test/resources/json/13typedef.c.json | 240 +- .../src/test/resources/json/14ushort.c.json | 248 +- .../src/test/resources/json/15addition.c.json | 200 +- .../src/test/resources/json/16loop.c.json | 317 +- .../test/resources/json/17recursive.c.json | 720 +++- .../test/resources/json/18multithread.c.json | 1127 +++-- .../src/test/resources/json/19dportest.c.json | 2622 ++++-------- .../test/resources/json/20testinline.c.json | 405 +- .../resources/json/21namecollision.c.json | 684 ++- .../src/test/resources/json/22nondet.c.json | 397 +- .../src/test/resources/json/23overflow.c.json | 166 +- .../src/test/resources/json/dekker.i.json | 3674 ++++++++++++----- .../hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt | 7 +- .../theta/xcfa/gson/XcfaLocationAdapter.kt | 56 +- .../java/hu/bme/mit/theta/xcfa/model/Dsl.kt | 6 +- .../hu/bme/mit/theta/xcfa/model/MetaData.kt | 10 +- .../theta/xcfa/passes/EliminateSelfLoops.kt | 8 +- .../theta/xcfa/passes/FinalLocationPass.kt | 5 +- .../xcfa/passes/FpFunctionsToExprsPass.kt | 2 +- .../theta/xcfa/passes/InlineProceduresPass.kt | 12 +- .../hu/bme/mit/theta/xcfa/passes/LbePass.kt | 11 +- .../mit/theta/xcfa/passes/LoopUnrollPass.kt | 2 +- .../theta/xcfa/passes/MallocFunctionPass.kt | 2 +- .../mit/theta/xcfa/passes/NoSideEffectPass.kt | 2 +- .../theta/xcfa/passes/NondetFunctionPass.kt | 2 +- .../hu/bme/mit/theta/xcfa/passes/Utils.kt | 11 +- .../hu/bme/mit/theta/xcfa/gson/GsonTest.kt | 3 +- .../mit/theta/xsts/analysis/XstsHornTest.java | 6 +- 57 files changed, 8559 insertions(+), 4991 deletions(-) diff --git a/.gitignore b/.gitignore index e68c7c1070..1bb6d2edce 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ xcfa.dot xcfa.json *.plantuml xcfa-*.smt2 +witness.yml diff --git a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java index 159cf1eb89..f1d0ef9bca 100644 --- a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java +++ b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java @@ -103,7 +103,7 @@ public Object visitChc_assert(CHCParser.Chc_assertContext ctx) { vars.put(ctx.chc_head().u_pred_atom().symbol(i++).getText(), param.getFirst()); } XcfaLocation middle = createLocation(procedure); - XcfaEdge edge = new XcfaEdge(procedure.getInitLoc(), middle, new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars))); + XcfaEdge edge = new XcfaEdge(procedure.getInitLoc(), middle, new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars)), EmptyMetaData.INSTANCE); procedure.addEdge(edge); createCalls(procedure, middle, procedure.getFinalLoc().get(), ctx.chc_tail().u_pred_atom(), vars); } else { @@ -115,7 +115,7 @@ public Object visitChc_assert(CHCParser.Chc_assertContext ctx) { } procedure = procedures.get(procName); Stmt returnTrue = AssignStmt.create(getOutParam(procedure), BoolLitExpr.of(true)); - XcfaEdge edge = new XcfaEdge(procedure.getInitLoc(), procedure.getFinalLoc().get(), new StmtLabel(returnTrue)); + XcfaEdge edge = new XcfaEdge(procedure.getInitLoc(), procedure.getFinalLoc().get(), new StmtLabel(returnTrue), EmptyMetaData.INSTANCE); procedure.addEdge(edge); } return super.visitChc_assert(ctx); @@ -128,7 +128,7 @@ public Object visitChc_query(CHCParser.Chc_queryContext ctx) { Map> vars = createVars(mainProcedure, ctx.var_decl()); XcfaLocation middle = createLocation(mainProcedure); - XcfaEdge edge = new XcfaEdge(mainProcedure.getInitLoc(), middle, new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars))); + XcfaEdge edge = new XcfaEdge(mainProcedure.getInitLoc(), middle, new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars)), EmptyMetaData.INSTANCE); mainProcedure.addEdge(edge); createCalls(mainProcedure, middle, mainProcedure.getErrorLoc().get(), ctx.chc_tail().u_pred_atom(), vars); return super.visitChc_query(ctx); @@ -137,7 +137,7 @@ public Object visitChc_query(CHCParser.Chc_queryContext ctx) { private int uniqeCounter = 0; private XcfaLocation createLocation(XcfaProcedureBuilder builder) { - XcfaLocation location = new XcfaLocation("l_" + uniqeCounter++); + XcfaLocation location = new XcfaLocation("l_" + uniqeCounter++, EmptyMetaData.INSTANCE); builder.addLoc(location); return location; } @@ -175,16 +175,16 @@ private void createCalls(XcfaProcedureBuilder builder, XcfaLocation start, XcfaL paramNames.add(0, ret.getName()); List> params = paramNames.stream().map(s -> localVars.get(s).getRef()).toList(); - XcfaEdge callEdge = new XcfaEdge(from, middle, new InvokeLabel(calledProcedure.getName(), params, EmptyMetaData.INSTANCE)); + XcfaEdge callEdge = new XcfaEdge(from, middle, new InvokeLabel(calledProcedure.getName(), params, EmptyMetaData.INSTANCE), EmptyMetaData.INSTANCE); builder.addEdge(callEdge); - XcfaEdge assertEdge = new XcfaEdge(middle, to, new StmtLabel(AssumeStmt.of(ret.getRef()))); + XcfaEdge assertEdge = new XcfaEdge(middle, to, new StmtLabel(AssumeStmt.of(ret.getRef())), EmptyMetaData.INSTANCE); builder.addEdge(assertEdge); from = to; } Stmt returnTrue = AssignStmt.create(getOutParam(builder), BoolLitExpr.of(true)); - XcfaEdge edge = new XcfaEdge(from, end, new StmtLabel(returnTrue)); + XcfaEdge edge = new XcfaEdge(from, end, new StmtLabel(returnTrue), EmptyMetaData.INSTANCE); builder.addEdge(edge); } } diff --git a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java index 732d58d975..04f591c913 100644 --- a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java +++ b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java @@ -22,14 +22,7 @@ import hu.bme.mit.theta.core.stmt.AssignStmt; import hu.bme.mit.theta.core.stmt.HavocStmt; import hu.bme.mit.theta.core.type.Type; -import hu.bme.mit.theta.xcfa.model.EmptyMetaData; -import hu.bme.mit.theta.xcfa.model.SequenceLabel; -import hu.bme.mit.theta.xcfa.model.StmtLabel; -import hu.bme.mit.theta.xcfa.model.XcfaBuilder; -import hu.bme.mit.theta.xcfa.model.XcfaEdge; -import hu.bme.mit.theta.xcfa.model.XcfaLabel; -import hu.bme.mit.theta.xcfa.model.XcfaLocation; -import hu.bme.mit.theta.xcfa.model.XcfaProcedureBuilder; +import hu.bme.mit.theta.xcfa.model.*; import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager; import java.util.ArrayList; @@ -37,10 +30,7 @@ import java.util.List; import java.util.Map; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.createVars; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.getTailConditionLabels; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.transformConst; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.transformSort; +import static hu.bme.mit.theta.frontend.chc.ChcUtils.*; public class ChcForwardXcfaBuilder extends CHCBaseVisitor implements ChcXcfaBuilder { private final ProcedurePassManager procedurePassManager; @@ -88,7 +78,7 @@ public Object visitFun_decl(CHCParser.Fun_declContext ctx) { builder.addVar(var); transformConst(Decls.Const(varName, type), true); } - XcfaLocation location = new XcfaLocation(name); + XcfaLocation location = new XcfaLocation(name, EmptyMetaData.INSTANCE); locations.put(name, new UPred(location, vars)); locations.put(ctx.symbol().getText(), new UPred(location, vars)); builder.addLoc(location); @@ -118,7 +108,7 @@ public Object visitChc_assert(CHCParser.Chc_assertContext ctx) { from = initLocation; to = locations.get(locName).location; } - XcfaEdge edge = new XcfaEdge(from, to, new SequenceLabel(labels)); + XcfaEdge edge = new XcfaEdge(from, to, new SequenceLabel(labels), EmptyMetaData.INSTANCE); builder.addEdge(edge); return super.visitChc_assert(ctx); } @@ -130,7 +120,7 @@ public Object visitChc_query(CHCParser.Chc_queryContext ctx) { List labels = new ArrayList<>(); labels.addAll(getIncomingAssignments(ctx.chc_tail(), vars)); labels.addAll(getTailConditionLabels(ctx.chc_tail(), vars)); - XcfaEdge edge = new XcfaEdge(from, errorLocation, new SequenceLabel(labels)); + XcfaEdge edge = new XcfaEdge(from, errorLocation, new SequenceLabel(labels), EmptyMetaData.INSTANCE); builder.addEdge(edge); return super.visitChc_query(ctx); } diff --git a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt index fe8d5ee0bd..d62b191661 100644 --- a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt +++ b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt @@ -15,11 +15,10 @@ */ package hu.bme.mit.theta.c2xcfa -import hu.bme.mit.theta.xcfa.model.MetaData -import hu.bme.mit.theta.xcfa.model.XcfaEdge -import hu.bme.mit.theta.xcfa.model.XcfaLabel -import hu.bme.mit.theta.xcfa.model.XcfaLocation +import hu.bme.mit.theta.xcfa.model.* import org.antlr.v4.runtime.ParserRuleContext +import kotlin.math.max +import kotlin.math.min data class CMetaData( val lineNumberStart: Int?, @@ -29,8 +28,38 @@ data class CMetaData( val offsetStart: Int?, val offsetEnd: Int?, val sourceText: String?, - val ctx: ParserRuleContext?, -) : MetaData() +) : MetaData() { + + override fun combine(other: MetaData): MetaData { + if (other is CMetaData) { + return CMetaData( + lineNumberStart = min( + lineNumberStart ?: other.lineNumberStart ?: -1, other.lineNumberStart ?: lineNumberStart ?: -1 + ).takeIf { it > 0 } ?: 0, + colNumberStart = min( + colNumberStart ?: other.colNumberStart ?: -1, other.colNumberStart ?: colNumberStart ?: -1 + ).takeIf { it > 0 } ?: 0, + offsetStart = min( + offsetStart ?: other.offsetStart ?: -1, other.offsetStart ?: offsetStart ?: -1 + ).takeIf { it > 0 } ?: 0, + lineNumberStop = max( + lineNumberStop ?: other.lineNumberStop ?: -1, other.lineNumberStop ?: lineNumberStop ?: -1 + ).takeIf { it > 0 } ?: 0, + colNumberStop = max( + colNumberStop ?: other.colNumberStop ?: -1, other.colNumberStop ?: colNumberStop ?: -1 + ).takeIf { it > 0 } ?: 0, + offsetEnd = max( + offsetEnd ?: other.offsetEnd ?: -1, other.offsetEnd ?: offsetEnd ?: -1 + ).takeIf { it > 0 } ?: 0, + sourceText = (sourceText ?: "") + (other.sourceText ?: ""), + ) + } else if (other is EmptyMetaData) { + return this + } else { + error("Cannot combine metadata of different types: $this vs $other") + } + } +} fun XcfaLabel.getCMetaData(): CMetaData? { return if (this.metadata is CMetaData) { diff --git a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt index 33355e8144..ebc4fd3da7 100644 --- a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt +++ b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt @@ -83,7 +83,6 @@ class FrontendXcfaBuilder(val parseContext: ParseContext, val checkOverflow: Boo offsetStart = source.offsetStart.takeIf { it != -1 }, offsetEnd = source.offsetEnd.takeIf { it != -1 }, sourceText = source.sourceText, - ctx = source.ctx, ) fun buildXcfa(cProgram: CProgram): XcfaBuilder { diff --git a/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java b/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java index a6e01016db..c6a06d5bb8 100644 --- a/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java +++ b/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java @@ -105,7 +105,7 @@ public XCFA visitMain(LitmusAArch64Parser.MainContext ctx) { for (Integer threadId : threadIds) { XcfaProcedureBuilder procBuilder = builders.get(threadId); procBuilder.createFinalLoc(); - procBuilder.addEdge(new XcfaEdge(lastLocation.get(threadId), procBuilder.getFinalLoc().get())); + procBuilder.addEdge(new XcfaEdge(lastLocation.get(threadId), procBuilder.getFinalLoc().get(), NopLabel.INSTANCE, EmptyMetaData.INSTANCE)); } return builder.build(); } @@ -142,7 +142,7 @@ private XcfaLocation newAnonymousLoc() { private XcfaLocation getOrCreateLoc(final String name) { if (!locations.get(currentProc).containsKey(name)) { - final XcfaLocation xcfaLocation = new XcfaLocation(name); + final XcfaLocation xcfaLocation = new XcfaLocation(name, EmptyMetaData.INSTANCE); builders.get(currentProc).addLoc(xcfaLocation); locations.get(currentProc).put(name, xcfaLocation); } @@ -278,11 +278,11 @@ public XcfaLocation visitBranchRegister32(LitmusAArch64Parser.BranchRegister32Co builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), branchTo, - stmt1)); + stmt1, EmptyMetaData.INSTANCE)); builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), newLoc, - stmt2)); + stmt2, EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -303,11 +303,11 @@ public XcfaLocation visitBranchRegister64(LitmusAArch64Parser.BranchRegister64Co builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), branchTo, - stmt1)); + stmt1, EmptyMetaData.INSTANCE)); builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), newLoc, - stmt2)); + stmt2, EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -318,7 +318,7 @@ public XcfaLocation visitBranch(LitmusAArch64Parser.BranchContext ctx) { final XcfaLocation newLoc = newAnonymousLoc(); builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), - branchTo)); + branchTo, NopLabel.INSTANCE, EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -328,7 +328,7 @@ public XcfaLocation visitBranchLabel(LitmusAArch64Parser.BranchLabelContext ctx) final XcfaLocation newLoc = getOrCreateLoc(ctx.label().getText()); builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), - newLoc)); + newLoc, NopLabel.INSTANCE, EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -341,7 +341,7 @@ public XcfaLocation visitSimpleInstruction(LitmusAArch64Parser.SimpleInstruction builders.get(currentProc).addEdge(new XcfaEdge( lastLocation.get(currentProc), newLoc, - label)); + label, EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java index c2d9d6af28..422517ddfd 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java @@ -17,6 +17,7 @@ package hu.bme.mit.theta.llvm2xcfa; import hu.bme.mit.theta.xcfa.model.MetaData; +import org.jetbrains.annotations.NotNull; public class LlvmMetadata extends MetaData { private final int lineNumber; @@ -24,4 +25,10 @@ public class LlvmMetadata extends MetaData { public LlvmMetadata(int lineNumber) { this.lineNumber = lineNumber; } + + @NotNull + @Override + public MetaData combine(@NotNull MetaData other) { + return this; + } } diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java index 010d621de5..f07bf60d2a 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java @@ -182,7 +182,7 @@ public static void foldExpression(Instruction instruction, FunctionState functio //noinspection OptionalGetWithoutIsPresent RegArgument ret = instruction.getRetVar().get(); if (ret instanceof LocalArgument) { - XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt()); + XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); VarDecl lhs = Utils.getOrCreateVar(functionState, ret); Stmt stmt = Assign(cast(lhs, lhs.getType()), cast(op, lhs.getType())); XcfaEdge edge; diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java index 8f6bac344e..45b7de6eae 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java @@ -77,7 +77,7 @@ private void setArrayElement(Instruction instruction, GlobalState globalState, F checkState(arr.getType() instanceof ArrayType, "getArrayElement used on non-array type."); checkState(idx.getType() == IntType.getInstance(), "getArrayElement used with non-int index."); - XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt()); + XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); VarDecl var = functionState.getLocalVars().get(arr.getName()).get1(); Expr expr = ArrayExprs.Write(cast(var.getRef(), ArrayType.of(Int(), val.getType())), cast(idx.getExpr(functionState.getValues()), Int()), cast(val.getExpr(functionState.getValues()), val.getType())); diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java index 45705421f7..82c0a2414d 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java @@ -109,7 +109,7 @@ private void store(Instruction instruction, GlobalState globalState, FunctionSta functionState.getValues().put(op1.getName(), var.getRef()); functionState.getValues().put(op2.getName(), var.getRef()); } else { - XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt()); + XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); VarDecl var = functionState.getLocalVars().get(op2.getName()).get1(); Stmt stmt = Assign(cast(var, var.getType()), cast(op1.getExpr(functionState.getValues()), var.getType())); XcfaEdge edge = new XcfaEdge(blockState.getLastLocation(), loc, new StmtLabel(stmt), new LlvmMetadata(instruction.getLineNumber())); diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java index 422a3639d4..80690a6595 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java @@ -36,11 +36,7 @@ import hu.bme.mit.theta.llvm2xcfa.handlers.states.FunctionState; import hu.bme.mit.theta.llvm2xcfa.handlers.states.GlobalState; import hu.bme.mit.theta.llvm2xcfa.handlers.utils.PlaceholderAssignmentStmt; -import hu.bme.mit.theta.xcfa.model.EmptyMetaData; -import hu.bme.mit.theta.xcfa.model.SequenceLabel; -import hu.bme.mit.theta.xcfa.model.StmtLabel; -import hu.bme.mit.theta.xcfa.model.XcfaEdge; -import hu.bme.mit.theta.xcfa.model.XcfaLocation; +import hu.bme.mit.theta.xcfa.model.*; import java.util.ArrayList; import java.util.List; @@ -50,12 +46,7 @@ import static hu.bme.mit.theta.core.stmt.Stmts.Assign; import static hu.bme.mit.theta.core.stmt.Stmts.Havoc; import static hu.bme.mit.theta.core.type.anytype.Exprs.Ite; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Eq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Geq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Gt; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Leq; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Lt; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Neq; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.*; import static hu.bme.mit.theta.core.utils.TypeUtils.cast; import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; import static hu.bme.mit.theta.llvm2xcfa.Utils.getOrCreateVar; @@ -94,7 +85,7 @@ public void handleInstruction(Instruction instruction, GlobalState globalState, private void call(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { Argument functionName = instruction.getArguments().get(instruction.getArguments().size() - 1); - XcfaLocation newLoc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt()); + XcfaLocation newLoc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); if (globalState.getProcedures().stream().anyMatch(objects -> objects.get1().equals(functionName.getName()))) { System.err.println("More than one function."); System.exit(-80); @@ -144,7 +135,7 @@ private void phi(Instruction instruction, GlobalState globalState, FunctionState Argument block = instruction.getArguments().get(2 * i + 1); Argument value = instruction.getArguments().get(2 * i); Tuple2 key = Tuple2.of(block.getName(), blockState.getName()); - Tuple4, Integer> val = functionState.getInterBlockEdges().getOrDefault(key, Tuple4.of(new XcfaLocation(key.get1()), new XcfaLocation(key.get2()), new ArrayList<>(), instruction.getLineNumber())); + Tuple4, Integer> val = functionState.getInterBlockEdges().getOrDefault(key, Tuple4.of(new XcfaLocation(key.get1(), EmptyMetaData.INSTANCE), new XcfaLocation(key.get2(), EmptyMetaData.INSTANCE), new ArrayList<>(), instruction.getLineNumber())); checkState(phiVar.getType().equals(value.getType()), "phiVar and value has to be of the same type!"); Stmt stmt; Expr expr; diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java index 7a866cd44c..7c4a26f388 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java @@ -99,7 +99,7 @@ public FunctionState(GlobalState globalState, Tuple3, L loc = procedureBuilder.getInitLoc(); first = false; } else { - loc = new XcfaLocation(block); + loc = new XcfaLocation(block, EmptyMetaData.INSTANCE); procedureBuilder.addLoc(loc); } locations.put(block, loc); diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt index f923d0e6f0..2fc5cbf6ba 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAnalysis.kt @@ -93,6 +93,7 @@ fun getCoreXcfaLts() = ReturnLabel(proc.value.returnStmts.peek()), ) ), + proc.value.locs.peek().metadata, ), nextCnt = s.sGlobal.nextCnt, ) @@ -105,6 +106,7 @@ fun getCoreXcfaLts() = proc.value.locs.peek(), proc.value.locs.peek(), proc.value.paramStmts.peek().first, + proc.value.locs.peek().metadata, ), nextCnt = s.sGlobal.nextCnt, ) diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt index a04508f9cf..a35a2ed980 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt @@ -38,11 +38,11 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory import hu.bme.mit.theta.xcfa.analysis.coi.ConeOfInfluence import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread import hu.bme.mit.theta.xcfa.analysis.por.* -import java.util.* -import kotlin.random.Random import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource +import java.util.* +import kotlin.random.Random class XcfaExplAnalysisTest { @@ -62,8 +62,6 @@ class XcfaExplAnalysisTest { } } - @ParameterizedTest - @MethodSource("data") fun testNoporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { println("Testing NOPOR on $filepath...") val stream = javaClass.getResourceAsStream(filepath) @@ -291,8 +289,6 @@ class XcfaExplAnalysisTest { Assertions.assertTrue(verdict(safetyResult)) } - @ParameterizedTest - @MethodSource("data") fun testAadporExpl(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { XcfaDporLts.random = Random(seed) println("Testing AADPOR on $filepath...") diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt index a10e82f096..c6932048db 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt @@ -38,11 +38,11 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory import hu.bme.mit.theta.xcfa.analysis.coi.ConeOfInfluence import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread import hu.bme.mit.theta.xcfa.analysis.por.* -import java.util.* -import kotlin.random.Random import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource +import java.util.* +import kotlin.random.Random class XcfaPredAnalysisTest { @@ -62,8 +62,6 @@ class XcfaPredAnalysisTest { } } - @ParameterizedTest - @MethodSource("data") fun testNoporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { println("Testing NOPOR on $filepath...") val stream = javaClass.getResourceAsStream(filepath) @@ -295,8 +293,6 @@ class XcfaPredAnalysisTest { Assertions.assertTrue(verdict(safetyResult)) } - @ParameterizedTest - @MethodSource("data") fun testAadporPred(filepath: String, verdict: (SafetyResult<*, *>) -> Boolean) { XcfaDporLts.random = Random(seed) println("Testing AADPOR on $filepath...") diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt index b1a815104b..67ffcf637f 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt @@ -95,7 +95,11 @@ class XcfaStateLtsTest { aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 } - actionOrder.add { XcfaAction(0, XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel))) } + actionOrder.add { + XcfaAction( + 0, XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel), EmptyMetaData) + ) + } expectations.add { it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[1].target && lts.getEnabledActionsFor(it).size == 1 && @@ -124,7 +128,9 @@ class XcfaStateLtsTest { } actionOrder.add { s -> - XcfaAction(s.foreignKey()!!, XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel))) + XcfaAction( + s.foreignKey()!!, XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel), EmptyMetaData) + ) } expectations.add { it.processes.size == 1 && it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[2].target && diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt index f8987c875e..5fe04637e1 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/ExecuteConfig.kt @@ -350,11 +350,11 @@ private fun postVerificationLogging( // TODO eliminate the need for the instanceof check if ( - !config.outputConfig.argConfig.disable && safetyResult.proof is ARG? + !config.outputConfig.argConfig.disable && safetyResult.proof is ARG ) { val argFile = File(resultFolder, "arg-${safetyResult.isSafe}.dot") val g: Graph = - ArgVisualizer.getDefault().visualize(safetyResult.proof as ARG?) + ArgVisualizer.getDefault().visualize(safetyResult.proof as ARG) argFile.writeText(GraphvizWriter.getInstance().writeString(g)) } @@ -366,7 +366,7 @@ private fun postVerificationLogging( ) { val concrTrace: Trace, XcfaAction> = XcfaTraceConcretizer.concretize( - safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, + safetyResult.asUnsafe().cex as Trace>, XcfaAction>, getSolver( config.outputConfig.witnessConfig.concretizerSolver, config.outputConfig.witnessConfig.validateConcretizerSolver, diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt index ad9011bd82..a7e0b45aa3 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt @@ -20,8 +20,8 @@ import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.reflect.TypeToken import hu.bme.mit.theta.analysis.Trace -import hu.bme.mit.theta.analysis.algorithm.arg.ARG import hu.bme.mit.theta.analysis.algorithm.SafetyResult +import hu.bme.mit.theta.analysis.algorithm.arg.ARG import hu.bme.mit.theta.analysis.expl.ExplState import hu.bme.mit.theta.analysis.pred.PredState import hu.bme.mit.theta.common.dsl.Env @@ -95,8 +95,7 @@ private fun getGson(scope: XcfaScope, env: Env, newScope: Boolean, domain: () -> gsonBuilder.registerTypeHierarchyAdapter(FrontendConfig::class.java, SpecFrontendConfigTypeAdapter { gson }) gsonBuilder.registerTypeHierarchyAdapter(BackendConfig::class.java, SpecBackendConfigTypeAdapter { gson }) gsonBuilder.registerTypeHierarchyAdapter(File::class.java, StringTypeAdapter { File(it) }) - gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, - StringTypeAdapter(xcfaLocationAdapter)) + gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, XcfaLocationAdapter { gson }) gsonBuilder.registerTypeHierarchyAdapter(XCFA::class.java, XcfaAdapter { gson }) gsonBuilder.registerTypeHierarchyAdapter(VarDecl::class.java, VarDeclAdapter({ gson }, scope, env, !newScope)) diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt index a6aa6b8bb5..8e0c2b4d39 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt @@ -21,6 +21,7 @@ import hu.bme.mit.theta.xcfa.cli.XcfaCli.Companion.main import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import java.io.File import java.util.stream.Stream import kotlin.io.path.createTempDirectory diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt index 3d29c73fb0..5ae3925c3e 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt @@ -16,14 +16,14 @@ package hu.bme.mit.theta.xcfa.cli import hu.bme.mit.theta.xcfa.cli.XcfaCli.Companion.main -import java.util.stream.Stream -import kotlin.io.path.absolutePathString -import kotlin.io.path.createTempDirectory -import kotlin.io.path.exists import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream +import kotlin.io.path.absolutePathString +import kotlin.io.path.createTempDirectory +import kotlin.io.path.exists data class WitnessEdge( val startlineRange: Pair?, @@ -46,8 +46,8 @@ class XcfaCliProofTest { WitnessEdge( startlineRange = Pair(5, 5), endlineRange = Pair(5, 5), - startoffsetRange = Pair(100, 130), - endoffsetRange = Pair(100, 130), + startoffsetRange = Pair(80, 82), + endoffsetRange = Pair(112, 114), assumption = Regex("i *== *-1"), ) ), @@ -59,8 +59,8 @@ class XcfaCliProofTest { WitnessEdge( startlineRange = Pair(5, 5), endlineRange = Pair(5, 5), - startoffsetRange = Pair(100, 130), - endoffsetRange = Pair(100, 130), + startoffsetRange = Pair(80, 82), + endoffsetRange = Pair(112, 114), assumption = Regex("i *== *-1"), ) ), diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/00assignment.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/00assignment.c.json index 4aec536b16..2baba2f1bb 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/00assignment.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/00assignment.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_661 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_661", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_661", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,21 +108,71 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::a", "type": "Int" + }, + { + "name": "call_reach_error_ret48", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_675 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 5, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 74, + "sourceText": "int main() {\n int a \u003d 1;\n if(a) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 5, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 74, + "sourceText": "int main() {\n int a \u003d 1;\n if(a) reach_error();\n}" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { "source": "main_init", - "target": "__loc_675", + "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -109,64 +197,18 @@ "content": "(assign main::a 1)" } ] - } - }, - { - "source": "__loc_675", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 7, - "offsetStart": 56, - "offsetEnd": 56, - "sourceText": "a" - } - }, - "content": "(assume (\u003d main::a 0))" - } - ] - } - }, - { - "source": "__loc_675", - "target": "main_error", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 7, - "offsetStart": 56, - "offsetEnd": 56, - "sourceText": "a" - } - }, - "content": "(assume (/\u003d main::a 0))" - } - ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 5, + "colNumberStop": 23, + "offsetStart": 21, + "offsetEnd": 74, + "sourceText": "int main() {\n int a \u003d 1;\n if(a) reach_error();\n}int a \u003d 1;\n if(a) reach_error();int a \u003d 1;int a \u003d 1;int a \u003d 1;int a \u003d 1;if(a) reach_error();if(a) reach_error();if(a) reach_error();if(a) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/01cast.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/01cast.c.json index 7820fde027..42a8d6308f 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/01cast.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/01cast.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_683 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_683", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_683", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,20 +108,86 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::a", "type": "Int" + }, + { + "name": "call___VERIFIER_nondet_ret49", + "type": "Int" + }, + { + "name": "call_reach_error_ret50", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_699 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 6, + "colNumberStop": 0, + "offsetStart": 46, + "offsetEnd": 123, + "sourceText": "int main() {\n int a \u003d __VERIFIER_nondet();\n if((char)a) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 6, + "colNumberStop": 0, + "offsetStart": 46, + "offsetEnd": 123, + "sourceText": "int main() {\n int a \u003d __VERIFIER_nondet();\n if((char)a) reach_error();\n}" + } + } + }, + { + "name": "__loc_679", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_699", + "source": "__loc_679", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -98,21 +202,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 5, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 5, - "colNumberStop": 13, - "offsetStart": 99, - "offsetEnd": 105, - "sourceText": "(char)a" + "colNumberStop": 29, + "offsetStart": 96, + "offsetEnd": 121, + "sourceText": "if((char)a) reach_error();" } }, - "content": "(assume (\u003d main::a 0))" + "content": "((assume (\u003d main::a 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 6, + "colNumberStop": 29, + "offsetStart": 46, + "offsetEnd": 123, + "sourceText": "if((char)a) reach_error();if((char)a) reach_error();int main() {\n int a \u003d __VERIFIER_nondet();\n if((char)a) reach_error();\n}" + } } }, { - "source": "__loc_699", + "source": "__loc_679", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -127,22 +243,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 5, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 5, - "colNumberStop": 13, - "offsetStart": 99, - "offsetEnd": 105, - "sourceText": "(char)a" + "colNumberStop": 29, + "offsetStart": 96, + "offsetEnd": 121, + "sourceText": "if((char)a) reach_error();" } }, - "content": "(assume (/\u003d main::a 0))" + "content": "((assume (/\u003d main::a 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 5, + "colNumberStop": 29, + "offsetStart": 96, + "offsetEnd": 121, + "sourceText": "if((char)a) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { "source": "main_init", - "target": "__loc_699", + "target": "__loc_679", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -156,12 +284,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 12, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 30, - "offsetStart": 71, - "offsetEnd": 89, - "sourceText": "__VERIFIER_nondet()" + "colNumberStop": 31, + "offsetStart": 63, + "offsetEnd": 90, + "sourceText": "int a \u003d __VERIFIER_nondet();" } }, "content": "(havoc main::a)" @@ -172,17 +300,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 12, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 30, - "offsetStart": 71, - "offsetEnd": 89, - "sourceText": "__VERIFIER_nondet()" + "colNumberStop": 31, + "offsetStart": 63, + "offsetEnd": 90, + "sourceText": "int a \u003d __VERIFIER_nondet();" } }, "content": "(assume (and (\u003e\u003d main::a -2147483648) (\u003c\u003d main::a 2147483647)))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 6, + "colNumberStop": 31, + "offsetStart": 46, + "offsetEnd": 123, + "sourceText": "int main() {\n int a \u003d __VERIFIER_nondet();\n if((char)a) reach_error();\n}int a \u003d __VERIFIER_nondet();\n if((char)a) reach_error();int a \u003d __VERIFIER_nondet();int a \u003d __VERIFIER_nondet();int a \u003d __VERIFIER_nondet();int a \u003d __VERIFIER_nondet();int a \u003d __VERIFIER_nondet();int a \u003d __VERIFIER_nondet();if((char)a) reach_error();if((char)a) reach_error();if((char)a) reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/02types.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/02types.c.json index 42d4d36d14..b571d3ff31 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/02types.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/02types.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_707 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_707", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_707", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,6 +108,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::a", "type": "Int" @@ -113,18 +155,76 @@ { "name": "main::ll", "type": "Int" + }, + { + "name": "call_reach_error_ret51", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_748 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 15, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 288, + "sourceText": "int main() {\n _Bool a;\n unsigned char uc;\n signed char c;\n unsigned short us;\n short s;\n unsigned int ui;\n int i;\n unsigned long ul;\n long l;\n unsigned long long ull;\n long long ll;\n if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 15, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 288, + "sourceText": "int main() {\n _Bool a;\n unsigned char uc;\n signed char c;\n unsigned short us;\n short s;\n unsigned int ui;\n int i;\n unsigned long ul;\n long l;\n unsigned long long ull;\n long long ll;\n if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();\n}" + } + } + }, + { + "name": "__loc_730", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "main_init", - "target": "__loc_748", + "source": "__loc_730", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -137,211 +237,169 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 14, + "colNumberStart": 4, + "lineNumberStop": 14, + "colNumberStop": 50, + "offsetStart": 240, + "offsetEnd": 286, + "sourceText": "if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();" } }, - "content": "(assume (and (\u003e\u003d main::a 0) (\u003c\u003d main::a 1)))" - }, + "content": "((assume (\u003d (mod (+ (mod main::a 18446744073709551616) (mod main::uc 18446744073709551616) (mod main::c 18446744073709551616) (mod main::us 18446744073709551616) (mod main::s 18446744073709551616) (mod main::ui 18446744073709551616) (mod main::i 18446744073709551616) (mod main::ul 18446744073709551616) (mod main::l 18446744073709551616) (mod main::ull 18446744073709551616) (mod main::ll 18446744073709551616)) 18446744073709551616) 0)))[choiceType\u003dALTERNATIVE_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 15, + "colNumberStop": 50, + "offsetStart": 21, + "offsetEnd": 288, + "sourceText": "if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();int main() {\n _Bool a;\n unsigned char uc;\n signed char c;\n unsigned short us;\n short s;\n unsigned int ui;\n int i;\n unsigned long ul;\n long l;\n unsigned long long ull;\n long long ll;\n if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();\n}" + } + } + }, + { + "source": "main_init", + "target": "__loc_730", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::uc 0) (\u003c\u003d main::uc 255)))" + "content": "((assume (and (\u003e\u003d main::a 0) (\u003c\u003d main::a 1))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::c -128) (\u003c\u003d main::c 127)))" + "content": "((assume (and (\u003e\u003d main::uc 0) (\u003c\u003d main::uc 255))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::us 0) (\u003c\u003d main::us 65535)))" + "content": "((assume (and (\u003e\u003d main::c -128) (\u003c\u003d main::c 127))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::s -32768) (\u003c\u003d main::s 32767)))" + "content": "((assume (and (\u003e\u003d main::us 0) (\u003c\u003d main::us 65535))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::ui 0) (\u003c\u003d main::ui 4294967295)))" + "content": "((assume (and (\u003e\u003d main::s -32768) (\u003c\u003d main::s 32767))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::i -2147483648) (\u003c\u003d main::i 2147483647)))" + "content": "((assume (and (\u003e\u003d main::ui 0) (\u003c\u003d main::ui 4294967295))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::ul 0) (\u003c\u003d main::ul 4294967295)))" + "content": "((assume (and (\u003e\u003d main::i -2147483648) (\u003c\u003d main::i 2147483647))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::l -2147483648) (\u003c\u003d main::l 2147483647)))" + "content": "((assume (and (\u003e\u003d main::ul 0) (\u003c\u003d main::ul 18446744073709551615))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::ull 0) (\u003c\u003d main::ull 18446744073709551615)))" + "content": "((assume (and (\u003e\u003d main::l -9223372036854775808) (\u003c\u003d main::l 9223372036854775807))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::ll -9223372036854775808) (\u003c\u003d main::ll 9223372036854775807)))" - } - ] - } - }, - { - "source": "__loc_748", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "((assume (and (\u003e\u003d main::ull 0) (\u003c\u003d main::ull 18446744073709551615))))[choiceType\u003dMAIN_PATH]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 14, - "colNumberStart": 7, - "lineNumberStop": 14, - "colNumberStop": 34, - "offsetStart": 243, - "offsetEnd": 270, - "sourceText": "a+uc+c+us+s+ui+i+ul+l+ull+ll" + "sourceText": "" } }, - "content": "(assume (\u003d (mod (+ (mod main::a 18446744073709551616) (mod main::uc 18446744073709551616) (mod main::c 18446744073709551616) (mod main::us 18446744073709551616) (mod main::s 18446744073709551616) (mod main::ui 18446744073709551616) (mod main::i 18446744073709551616) (mod main::ul 18446744073709551616) (mod main::l 18446744073709551616) (mod main::ull 18446744073709551616) (mod main::ll 18446744073709551616)) 18446744073709551616) 0))" + "content": "((assume (and (\u003e\u003d main::ll -9223372036854775808) (\u003c\u003d main::ll 9223372036854775807))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 15, + "colNumberStop": 50, + "offsetStart": 21, + "offsetEnd": 288, + "sourceText": "int main() {\n _Bool a;\n unsigned char uc;\n signed char c;\n unsigned short us;\n short s;\n unsigned int ui;\n int i;\n unsigned long ul;\n long l;\n unsigned long long ull;\n long long ll;\n if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();\n}_Bool a;\n unsigned char uc;\n signed char c;\n unsigned short us;\n short s;\n unsigned int ui;\n int i;\n unsigned long ul;\n long l;\n unsigned long long ull;\n long long ll;\n if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();_Bool a;unsigned char uc;signed char c;unsigned short us;short s;unsigned int ui;int i;unsigned long ul;long l;unsigned long long ull;long long ll;if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();" + } } }, { - "source": "__loc_748", + "source": "__loc_730", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -356,17 +414,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 14, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 14, - "colNumberStop": 34, - "offsetStart": 243, - "offsetEnd": 270, - "sourceText": "a+uc+c+us+s+ui+i+ul+l+ull+ll" + "colNumberStop": 50, + "offsetStart": 240, + "offsetEnd": 286, + "sourceText": "if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();" } }, - "content": "(assume (/\u003d (mod (+ (mod main::a 18446744073709551616) (mod main::uc 18446744073709551616) (mod main::c 18446744073709551616) (mod main::us 18446744073709551616) (mod main::s 18446744073709551616) (mod main::ui 18446744073709551616) (mod main::i 18446744073709551616) (mod main::ul 18446744073709551616) (mod main::l 18446744073709551616) (mod main::ull 18446744073709551616) (mod main::ll 18446744073709551616)) 18446744073709551616) 0))" + "content": "((assume (/\u003d (mod (+ (mod main::a 18446744073709551616) (mod main::uc 18446744073709551616) (mod main::c 18446744073709551616) (mod main::us 18446744073709551616) (mod main::s 18446744073709551616) (mod main::ui 18446744073709551616) (mod main::i 18446744073709551616) (mod main::ul 18446744073709551616) (mod main::l 18446744073709551616) (mod main::ull 18446744073709551616) (mod main::ll 18446744073709551616)) 18446744073709551616) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 14, + "colNumberStart": 4, + "lineNumberStop": 14, + "colNumberStop": 50, + "offsetStart": 240, + "offsetEnd": 286, + "sourceText": "if(a+uc+c+us+s+ui+i+ul+l+ull+ll) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/03bitwise.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/03bitwise.c.json index 3a04f5c917..bb26165a44 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/03bitwise.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/03bitwise.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_756 " + "vars": [ + { + "name": "reach_error_ret", + "type": "(Bv 1)" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_756", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_756", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,20 +108,86 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "(Bv 32)" + }, { "name": "main::a", "type": "(Bv 32)" + }, + { + "name": "call___VERIFIER_nondet_int_ret52", + "type": "(Bv 32)" + }, + { + "name": "call_reach_error_ret53", + "type": "(Bv 1)" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_781 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 50, + "offsetEnd": 147, + "sourceText": "int main() {\n int a \u003d __VERIFIER_nondet_int();\n a \u003d a | 0;\n if(a \u003d\u003d -10) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 50, + "offsetEnd": 147, + "sourceText": "int main() {\n int a \u003d __VERIFIER_nondet_int();\n a \u003d a | 0;\n if(a \u003d\u003d -10) reach_error();\n}" + } + } + }, + { + "name": "__loc_763", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_781", + "source": "__loc_763", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -98,21 +202,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 6, - "colNumberStop": 14, - "offsetStart": 122, - "offsetEnd": 129, - "sourceText": "a \u003d\u003d -10" + "colNumberStop": 30, + "offsetStart": 119, + "offsetEnd": 145, + "sourceText": "if(a \u003d\u003d -10) reach_error();" } }, - "content": "(assume (\u003d (ite (\u003d main::a #b11111111111111111111111111110110) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000))" + "content": "((assume (\u003d (ite (\u003d main::a #b11111111111111111111111111110110) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 30, + "offsetStart": 50, + "offsetEnd": 147, + "sourceText": "if(a \u003d\u003d -10) reach_error();if(a \u003d\u003d -10) reach_error();int main() {\n int a \u003d __VERIFIER_nondet_int();\n a \u003d a | 0;\n if(a \u003d\u003d -10) reach_error();\n}" + } } }, { - "source": "__loc_781", + "source": "__loc_763", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -127,22 +243,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 6, - "colNumberStop": 14, - "offsetStart": 122, - "offsetEnd": 129, - "sourceText": "a \u003d\u003d -10" + "colNumberStop": 30, + "offsetStart": 119, + "offsetEnd": 145, + "sourceText": "if(a \u003d\u003d -10) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003d main::a #b11111111111111111111111111110110) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000))" + "content": "((assume (/\u003d (ite (\u003d main::a #b11111111111111111111111111110110) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 30, + "offsetStart": 119, + "offsetEnd": 145, + "sourceText": "if(a \u003d\u003d -10) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { "source": "main_init", - "target": "__loc_781", + "target": "__loc_763", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -156,12 +284,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 12, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 34, - "offsetStart": 75, - "offsetEnd": 97, - "sourceText": "__VERIFIER_nondet_int()" + "colNumberStop": 35, + "offsetStart": 67, + "offsetEnd": 98, + "sourceText": "int a \u003d __VERIFIER_nondet_int();" } }, "content": "(havoc main::a)" @@ -172,12 +300,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 12, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 34, - "offsetStart": 75, - "offsetEnd": 97, - "sourceText": "__VERIFIER_nondet_int()" + "colNumberStop": 35, + "offsetStart": 67, + "offsetEnd": 98, + "sourceText": "int a \u003d __VERIFIER_nondet_int();" } }, "content": "(assume true)" @@ -187,18 +315,24 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, "content": "(assign main::a main::a)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 35, + "offsetStart": 0, + "offsetEnd": 147, + "sourceText": "int main() {\n int a \u003d __VERIFIER_nondet_int();\n a \u003d a | 0;\n if(a \u003d\u003d -10) reach_error();\n}int a \u003d __VERIFIER_nondet_int();\n a \u003d a | 0;\n if(a \u003d\u003d -10) reach_error();int a \u003d __VERIFIER_nondet_int();int a \u003d __VERIFIER_nondet_int();int a \u003d __VERIFIER_nondet_int();int a \u003d __VERIFIER_nondet_int();int a \u003d __VERIFIER_nondet_int();int a \u003d __VERIFIER_nondet_int();a \u003d a | 0;a \u003d a | 0;a \u003d a | 0;if(a \u003d\u003d -10) reach_error();if(a \u003d\u003d -10) reach_error();if(a \u003d\u003d -10) reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/04real.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/04real.c.json index 32d9c9f41d..36d590aab5 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/04real.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/04real.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_789 " + "vars": [ + { + "name": "reach_error_ret", + "type": "(Bv 1)" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_789", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_789", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,6 +108,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "(Bv 32)" + }, { "name": "main::f", "type": "(Fp 8 24)" @@ -81,17 +123,79 @@ { "name": "main::ld", "type": "(Fp 15 113)" + }, + { + "name": "call___VERIFIER_nondet_float_ret54", + "type": "(Fp 8 24)" + }, + { + "name": "call_reach_error_ret55", + "type": "(Bv 1)" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_817 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 0, + "offsetStart": 61, + "offsetEnd": 205, + "sourceText": "int main() {\n float f \u003d __VERIFIER_nondet_float();\n double d \u003d f;\n long double ld \u003d d;\n if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 0, + "offsetStart": 61, + "offsetEnd": 205, + "sourceText": "int main() {\n float f \u003d __VERIFIER_nondet_float();\n double d \u003d f;\n long double ld \u003d d;\n if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();\n}" + } + } + }, + { + "name": "__loc_801", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_817", + "source": "__loc_801", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -106,21 +210,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 7, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 7, - "colNumberStop": 30, - "offsetStart": 164, - "offsetEnd": 187, - "sourceText": "ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f" + "colNumberStop": 46, + "offsetStart": 161, + "offsetEnd": 203, + "sourceText": "if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();" } }, - "content": "(assume (\u003d (ite (and (/\u003d #b00000000000000000000000000000000 (ite (\u003e main::ld (#b0 #b011111111111101 #b0001111010111000010100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000)) (/\u003d #b00000000000000000000000000000000 (ite (\u003c main::ld (#b0 #b011111111111101 #b0100011110101110000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000))) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000))" + "content": "((assume (\u003d (ite (and (/\u003d #b00000000000000000000000000000000 (ite (\u003e main::ld (#b0 #b011111111111101 #b0001111010111000010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000)) (/\u003d #b00000000000000000000000000000000 (ite (\u003c main::ld (#b0 #b011111111111101 #b0100011110101110000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000))) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 46, + "offsetStart": 61, + "offsetEnd": 205, + "sourceText": "if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();int main() {\n float f \u003d __VERIFIER_nondet_float();\n double d \u003d f;\n long double ld \u003d d;\n if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();\n}" + } } }, { - "source": "__loc_817", + "source": "__loc_801", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -135,22 +251,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 7, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 7, - "colNumberStop": 30, - "offsetStart": 164, - "offsetEnd": 187, - "sourceText": "ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f" + "colNumberStop": 46, + "offsetStart": 161, + "offsetEnd": 203, + "sourceText": "if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();" } }, - "content": "(assume (/\u003d (ite (and (/\u003d #b00000000000000000000000000000000 (ite (\u003e main::ld (#b0 #b011111111111101 #b0001111010111000010100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000)) (/\u003d #b00000000000000000000000000000000 (ite (\u003c main::ld (#b0 #b011111111111101 #b0100011110101110000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000))) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000))" + "content": "((assume (/\u003d (ite (and (/\u003d #b00000000000000000000000000000000 (ite (\u003e main::ld (#b0 #b011111111111101 #b0001111010111000010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000)) (/\u003d #b00000000000000000000000000000000 (ite (\u003c main::ld (#b0 #b011111111111101 #b0100011110101110000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)) #b00000000000000000000000000000001 #b00000000000000000000000000000000))) #b00000000000000000000000000000001 #b00000000000000000000000000000000) #b00000000000000000000000000000000)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 7, + "colNumberStart": 4, + "lineNumberStop": 7, + "colNumberStop": 46, + "offsetStart": 161, + "offsetEnd": 203, + "sourceText": "if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { "source": "main_init", - "target": "__loc_817", + "target": "__loc_801", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -164,12 +292,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 14, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 38, - "offsetStart": 88, - "offsetEnd": 112, - "sourceText": "__VERIFIER_nondet_float()" + "colNumberStop": 39, + "offsetStart": 78, + "offsetEnd": 113, + "sourceText": "float f \u003d __VERIFIER_nondet_float();" } }, "content": "(havoc main::f)" @@ -180,12 +308,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 14, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 38, - "offsetStart": 88, - "offsetEnd": 112, - "sourceText": "__VERIFIER_nondet_float()" + "colNumberStop": 39, + "offsetStart": 78, + "offsetEnd": 113, + "sourceText": "float f \u003d __VERIFIER_nondet_float();" } }, "content": "(assume true)" @@ -223,6 +351,18 @@ "content": "(assign main::ld (fptofp[15,113] main::d))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 46, + "offsetStart": 61, + "offsetEnd": 205, + "sourceText": "int main() {\n float f \u003d __VERIFIER_nondet_float();\n double d \u003d f;\n long double ld \u003d d;\n if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();\n}float f \u003d __VERIFIER_nondet_float();\n double d \u003d f;\n long double ld \u003d d;\n if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();float f \u003d __VERIFIER_nondet_float();float f \u003d __VERIFIER_nondet_float();float f \u003d __VERIFIER_nondet_float();float f \u003d __VERIFIER_nondet_float();float f \u003d __VERIFIER_nondet_float();float f \u003d __VERIFIER_nondet_float();double d \u003d f;double d \u003d f;double d \u003d f;double d \u003d f;long double ld \u003d d;long double ld \u003d d;long double ld \u003d d;long double ld \u003d d;if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();if(ld \u003e 0.28f \u0026\u0026 ld \u003c 0.32f) reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/05math.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/05math.c.json index 8059ad3735..36e3ea01a1 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/05math.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/05math.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_825 " + "vars": [ + { + "name": "reach_error_ret", + "type": "(Bv 1)" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_825", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_825", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,6 +108,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "(Bv 32)" + }, { "name": "main::f", "type": "(Fp 8 24)" @@ -137,18 +179,117 @@ { "name": "call_isnan_ret63", "type": "(Bv 32)" + }, + { + "name": "call_reach_error_ret64", + "type": "(Bv 1)" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_942 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 0, + "lineNumberStop": 22, + "colNumberStop": 0, + "offsetStart": 170, + "offsetEnd": 459, + "sourceText": "int main() {\n float f \u003d 12.65f;\n float f1 \u003d fabs(f);\n float f2 \u003d floor(f);\n float f3 \u003d round(f);\n float f4 \u003d fmax(f2, f3);\n float f5 \u003d fmin(f2, f3);\n float f6 \u003d sqrt(f);\n float f7 \u003d isnan(f);\n f \u003d 0.0f;\n float f8 \u003d isnan(0.0f/0.0f);\n if(f8) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 0, + "lineNumberStop": 22, + "colNumberStop": 0, + "offsetStart": 170, + "offsetEnd": 459, + "sourceText": "int main() {\n float f \u003d 12.65f;\n float f1 \u003d fabs(f);\n float f2 \u003d floor(f);\n float f3 \u003d round(f);\n float f4 \u003d fmax(f2, f3);\n float f5 \u003d fmin(f2, f3);\n float f6 \u003d sqrt(f);\n float f7 \u003d isnan(f);\n f \u003d 0.0f;\n float f8 \u003d isnan(0.0f/0.0f);\n if(f8) reach_error();\n}" + } + } + }, + { + "name": "__loc_926", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ + { + "source": "__loc_926", + "target": "main_final", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 21, + "colNumberStart": 4, + "lineNumberStop": 21, + "colNumberStop": 24, + "offsetStart": 437, + "offsetEnd": 457, + "sourceText": "if(f8) reach_error();" + } + }, + "content": "((assume (\u003d main::f8 (#b0 #b00000000 #b00000000000000000000000))))[choiceType\u003dALTERNATIVE_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 0, + "lineNumberStop": 22, + "colNumberStop": 24, + "offsetStart": 170, + "offsetEnd": 459, + "sourceText": "if(f8) reach_error();if(f8) reach_error();int main() {\n float f \u003d 12.65f;\n float f1 \u003d fabs(f);\n float f2 \u003d floor(f);\n float f3 \u003d round(f);\n float f4 \u003d fmax(f2, f3);\n float f5 \u003d fmin(f2, f3);\n float f6 \u003d sqrt(f);\n float f7 \u003d isnan(f);\n f \u003d 0.0f;\n float f8 \u003d isnan(0.0f/0.0f);\n if(f8) reach_error();\n}" + } + } + }, { "source": "main_init", - "target": "__loc_942", + "target": "__loc_926", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -178,15 +319,15 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 12, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 12, - "colNumberStop": 21, - "offsetStart": 220, - "offsetEnd": 226, - "sourceText": "fabs(f)" + "colNumberStop": 22, + "offsetStart": 209, + "offsetEnd": 227, + "sourceText": "float f1 \u003d fabs(f);" } }, - "content": "(assign call_fabs_ret56 (fpabs main::f))" + "content": "(assign call_fabs_ret56 (fpabs (#b0 #b10000010 #b10010100110011001100110)))" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -210,15 +351,15 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 13, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 13, - "colNumberStop": 22, - "offsetStart": 244, - "offsetEnd": 251, - "sourceText": "floor(f)" + "colNumberStop": 23, + "offsetStart": 233, + "offsetEnd": 252, + "sourceText": "float f2 \u003d floor(f);" } }, - "content": "(assign call_floor_ret57 (fproundtoint main::f))" + "content": "(assign call_floor_ret57 (fproundtoint[RTN] (#b0 #b10000010 #b10010100110011001100110)))" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -242,15 +383,15 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 14, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 14, - "colNumberStop": 22, - "offsetStart": 269, - "offsetEnd": 276, - "sourceText": "round(f)" + "colNumberStop": 23, + "offsetStart": 258, + "offsetEnd": 277, + "sourceText": "float f3 \u003d round(f);" } }, - "content": "(assign call_round_ret58 (fproundtoint main::f))" + "content": "(assign call_round_ret58 (fproundtoint[RNA] (#b0 #b10000010 #b10010100110011001100110)))" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -274,12 +415,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 15, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 15, - "colNumberStop": 26, - "offsetStart": 294, - "offsetEnd": 305, - "sourceText": "fmax(f2, f3)" + "colNumberStop": 27, + "offsetStart": 283, + "offsetEnd": 306, + "sourceText": "float f4 \u003d fmax(f2, f3);" } }, "content": "(assign call_fmax_ret59 (fpmax main::f2 main::f3))" @@ -306,12 +447,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 16, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 16, - "colNumberStop": 26, - "offsetStart": 323, - "offsetEnd": 334, - "sourceText": "fmin(f2, f3)" + "colNumberStop": 27, + "offsetStart": 312, + "offsetEnd": 335, + "sourceText": "float f5 \u003d fmin(f2, f3);" } }, "content": "(assign call_fmin_ret60 (fpmin main::f2 main::f3))" @@ -338,15 +479,15 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 17, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 17, - "colNumberStop": 21, - "offsetStart": 352, - "offsetEnd": 358, - "sourceText": "sqrt(f)" + "colNumberStop": 22, + "offsetStart": 341, + "offsetEnd": 359, + "sourceText": "float f6 \u003d sqrt(f);" } }, - "content": "(assign call_sqrt_ret61 (fpsqrt main::f))" + "content": "(assign call_sqrt_ret61 (#b0 #b10000000 #b11000111010000010110101))" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -362,7 +503,7 @@ "sourceText": "float f6 \u003d sqrt(f);" } }, - "content": "(assign main::f6 call_sqrt_ret61)" + "content": "(assign main::f6 (#b0 #b10000000 #b11000111010000010110101))" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -370,15 +511,15 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 18, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 18, - "colNumberStop": 22, - "offsetStart": 376, - "offsetEnd": 383, - "sourceText": "isnan(f)" + "colNumberStop": 23, + "offsetStart": 365, + "offsetEnd": 384, + "sourceText": "float f7 \u003d isnan(f);" } }, - "content": "(assign call_isnan_ret62 (ite (fpisnan main::f) #b00000000000000000000000000000001 #b00000000000000000000000000000000))" + "content": "(assign call_isnan_ret62 #b00000000000000000000000000000000)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -394,19 +535,13 @@ "sourceText": "float f7 \u003d isnan(f);" } }, - "content": "(assign main::f7 (fpfrombv[8,24][s] call_isnan_ret62))" + "content": "(assign main::f7 (#b0 #b00000000 #b00000000000000000000000))" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -418,12 +553,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 20, - "colNumberStart": 15, + "colNumberStart": 4, "lineNumberStop": 20, - "colNumberStop": 30, - "offsetStart": 415, - "offsetEnd": 430, - "sourceText": "isnan(0.0f/0.0f)" + "colNumberStop": 31, + "offsetStart": 404, + "offsetEnd": 431, + "sourceText": "float f8 \u003d isnan(0.0f/0.0f);" } }, "content": "(assign call_isnan_ret63 (ite (fpisnan (fpdiv[rne] (#b0 #b00000000 #b00000000000000000000000) (#b0 #b00000000 #b00000000000000000000000))) #b00000000000000000000000000000001 #b00000000000000000000000000000000))" @@ -445,39 +580,22 @@ "content": "(assign main::f8 (fpfrombv[8,24][s] call_isnan_ret63))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 22, + "colNumberStop": 31, + "offsetStart": 0, + "offsetEnd": 459, + "sourceText": "int main() {\n float f \u003d 12.65f;\n float f1 \u003d fabs(f);\n float f2 \u003d floor(f);\n float f3 \u003d round(f);\n float f4 \u003d fmax(f2, f3);\n float f5 \u003d fmin(f2, f3);\n float f6 \u003d sqrt(f);\n float f7 \u003d isnan(f);\n f \u003d 0.0f;\n float f8 \u003d isnan(0.0f/0.0f);\n if(f8) reach_error();\n}float f \u003d 12.65f;\n float f1 \u003d fabs(f);\n float f2 \u003d floor(f);\n float f3 \u003d round(f);\n float f4 \u003d fmax(f2, f3);\n float f5 \u003d fmin(f2, f3);\n float f6 \u003d sqrt(f);\n float f7 \u003d isnan(f);\n f \u003d 0.0f;\n float f8 \u003d isnan(0.0f/0.0f);\n if(f8) reach_error();float f \u003d 12.65f;float f \u003d 12.65f;float f \u003d 12.65f;float f \u003d 12.65f;float f1 \u003d fabs(f);float f1 \u003d fabs(f);float f1 \u003d fabs(f);float f1 \u003d fabs(f);float f1 \u003d fabs(f);float f1 \u003d fabs(f);float f1 \u003d fabs(f);float f2 \u003d floor(f);float f2 \u003d floor(f);float f2 \u003d floor(f);float f2 \u003d floor(f);float f2 \u003d floor(f);float f2 \u003d floor(f);float f2 \u003d floor(f);float f3 \u003d round(f);float f3 \u003d round(f);float f3 \u003d round(f);float f3 \u003d round(f);float f3 \u003d round(f);float f3 \u003d round(f);float f3 \u003d round(f);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f4 \u003d fmax(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f5 \u003d fmin(f2, f3);float f6 \u003d sqrt(f);float f6 \u003d sqrt(f);float f6 \u003d sqrt(f);float f6 \u003d sqrt(f);float f6 \u003d sqrt(f);float f6 \u003d sqrt(f);float f6 \u003d sqrt(f);float f7 \u003d isnan(f);float f7 \u003d isnan(f);float f7 \u003d isnan(f);float f7 \u003d isnan(f);float f7 \u003d isnan(f);float f7 \u003d isnan(f);float f7 \u003d isnan(f);f \u003d 0.0f;f \u003d 0.0f;f \u003d 0.0f;float f8 \u003d isnan(0.0f/0.0f);float f8 \u003d isnan(0.0f/0.0f);float f8 \u003d isnan(0.0f/0.0f);float f8 \u003d isnan(0.0f/0.0f);float f8 \u003d isnan(0.0f/0.0f);float f8 \u003d isnan(0.0f/0.0f);float f8 \u003d isnan(0.0f/0.0f);if(f8) reach_error();if(f8) reach_error();if(f8) reach_error();" + } } }, { - "source": "__loc_942", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 21, - "colNumberStart": 7, - "lineNumberStop": 21, - "colNumberStop": 8, - "offsetStart": 440, - "offsetEnd": 441, - "sourceText": "f8" - } - }, - "content": "(assume (\u003d main::f8 (#b0 #b00000000 #b00000000000000000000000)))" - } - ] - } - }, - { - "source": "__loc_942", + "source": "__loc_926", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -492,17 +610,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 21, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 21, - "colNumberStop": 8, - "offsetStart": 440, - "offsetEnd": 441, - "sourceText": "f8" + "colNumberStop": 24, + "offsetStart": 437, + "offsetEnd": 457, + "sourceText": "if(f8) reach_error();" } }, - "content": "(assume (/\u003d main::f8 (#b0 #b00000000 #b00000000000000000000000)))" + "content": "((assume (/\u003d main::f8 (#b0 #b00000000 #b00000000000000000000000))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 21, + "colNumberStart": 4, + "lineNumberStop": 21, + "colNumberStop": 24, + "offsetStart": 437, + "offsetEnd": 457, + "sourceText": "if(f8) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/06arrays.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/06arrays.c.json index 2407fd19ce..a98cac5d00 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/06arrays.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/06arrays.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_950 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_950", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_950", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,25 +108,87 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::a", - "type": "(Array ([Int] -\u003e Int))" + "type": "Int" }, { "name": "main::b", - "type": "(Array ([Int] -\u003e Int))" + "type": "Int" + }, + { + "name": "call_reach_error_ret65", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_977 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 0, + "offsetStart": 22, + "offsetEnd": 120, + "sourceText": "int main() {\n int a[2], b[3];\n a[0] \u003d 12;\n b[3] \u003d a[0];\n if(b[3] \u003e 11) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 0, + "offsetStart": 22, + "offsetEnd": 120, + "sourceText": "int main() {\n int a[2], b[3];\n a[0] \u003d 12;\n b[3] \u003d a[0];\n if(b[3] \u003e 11) reach_error();\n}" + } + } + }, + { + "name": "__loc_963", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "main_init", - "target": "__loc_977", + "source": "__loc_963", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -101,39 +201,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" - } - }, - "content": "(assign main::a (write main::a 0 12))" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 7, + "colNumberStart": 4, + "lineNumberStop": 7, + "colNumberStop": 31, + "offsetStart": 91, + "offsetEnd": 118, + "sourceText": "if(b[3] \u003e 11) reach_error();" } }, - "content": "(assign main::b (write main::b 3 (read main::a 0)))" + "content": "((assume (\u003d (ite (\u003e (deref 4 3 Int) 11) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 31, + "offsetStart": 22, + "offsetEnd": 120, + "sourceText": "if(b[3] \u003e 11) reach_error();if(b[3] \u003e 11) reach_error();int main() {\n int a[2], b[3];\n a[0] \u003d 12;\n b[3] \u003d a[0];\n if(b[3] \u003e 11) reach_error();\n}" + } } }, { - "source": "__loc_977", - "target": "main_final", + "source": "main_init", + "target": "__loc_963", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -141,27 +237,59 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign main::a 1)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign main::b 4)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 7, - "colNumberStart": 7, - "lineNumberStop": 7, - "colNumberStop": 15, - "offsetStart": 94, - "offsetEnd": 102, - "sourceText": "b[3] \u003e 11" + "sourceText": "" } }, - "content": "(assume (\u003d (ite (\u003e (read main::b 3) 11) 1 0) 0))" + "content": "(memassign (deref 1 0 Int) 12)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + }, + "content": "(memassign (deref 4 3 Int) (deref 1 0 Int))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 31, + "offsetStart": 0, + "offsetEnd": 120, + "sourceText": "int main() {\n int a[2], b[3];\n a[0] \u003d 12;\n b[3] \u003d a[0];\n if(b[3] \u003e 11) reach_error();\n}int a[2], b[3];\n a[0] \u003d 12;\n b[3] \u003d a[0];\n if(b[3] \u003e 11) reach_error();int a[2], b[3];a[0] \u003d 12;a[0] \u003d 12;a[0] \u003d 12;b[3] \u003d a[0];b[3] \u003d a[0];b[3] \u003d a[0];if(b[3] \u003e 11) reach_error();if(b[3] \u003e 11) reach_error();if(b[3] \u003e 11) reach_error();" + } } }, { - "source": "__loc_977", + "source": "__loc_963", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -176,17 +304,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 7, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 7, - "colNumberStop": 15, - "offsetStart": 94, - "offsetEnd": 102, - "sourceText": "b[3] \u003e 11" + "colNumberStop": 31, + "offsetStart": 91, + "offsetEnd": 118, + "sourceText": "if(b[3] \u003e 11) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003e (read main::b 3) 11) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003e (deref 4 3 Int) 11) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 7, + "colNumberStart": 4, + "lineNumberStop": 7, + "colNumberStop": 31, + "offsetStart": 91, + "offsetEnd": 118, + "sourceText": "if(b[3] \u003e 11) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/07arrayinit.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/07arrayinit.c.json index 5cd64a5e20..07158dc5a0 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/07arrayinit.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/07arrayinit.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_985 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_985", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_985", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,25 +108,128 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::x", "type": "Int" }, { "name": "main::a", - "type": "(Array ([Int] -\u003e Int))" + "type": "Int" + }, + { + "name": "call_reach_error_ret66", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1008 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 107, + "sourceText": "int main() {\n int x;\n int a[3] \u003d {2, x+1, 4};\n if(a[1] \u003e 2) reach_error();\n }" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 107, + "sourceText": "int main() {\n int x;\n int a[3] \u003d {2, x+1, 4};\n if(a[1] \u003e 2) reach_error();\n }" + } + } + }, + { + "name": "__loc_991", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ + { + "source": "__loc_991", + "target": "main_final", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 30, + "offsetStart": 78, + "offsetEnd": 104, + "sourceText": "if(a[1] \u003e 2) reach_error();" + } + }, + "content": "((assume (\u003d (ite (\u003e (deref 1 1 Int) 2) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 30, + "offsetStart": 22, + "offsetEnd": 107, + "sourceText": "if(a[1] \u003e 2) reach_error();if(a[1] \u003e 2) reach_error();int main() {\n int x;\n int a[3] \u003d {2, x+1, 4};\n if(a[1] \u003e 2) reach_error();\n }" + } + } + }, { "source": "main_init", - "target": "__loc_1008", + "target": "__loc_991", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -96,21 +237,23 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign main::a 1)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::x -2147483648) (\u003c\u003d main::x 2147483647)))" + "content": "((assume (and (\u003e\u003d main::x -2147483648) (\u003c\u003d main::x 2147483647))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -126,42 +269,57 @@ "sourceText": "int a[3] \u003d {2, x+1, 4};" } }, - "content": "(assign main::a (arrayinit 0 0 1 2 2 (+ main::x 1) 4))" - } - ] - } - }, - { - "source": "__loc_1008", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(memassign (deref 1 0 Int) 2)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, - "colNumberStart": 7, - "lineNumberStop": 6, - "colNumberStop": 14, - "offsetStart": 81, - "offsetEnd": 88, - "sourceText": "a[1] \u003e 2" + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 5, + "colNumberStop": 26, + "offsetStart": 50, + "offsetEnd": 72, + "sourceText": "int a[3] \u003d {2, x+1, 4};" + } + }, + "content": "(memassign (deref 1 1 Int) (+ main::x 1))" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 5, + "colNumberStop": 26, + "offsetStart": 50, + "offsetEnd": 72, + "sourceText": "int a[3] \u003d {2, x+1, 4};" } }, - "content": "(assume (\u003d (ite (\u003e (read main::a 1) 2) 1 0) 0))" + "content": "(memassign (deref 1 2 Int) 4)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 30, + "offsetStart": 22, + "offsetEnd": 107, + "sourceText": "int main() {\n int x;\n int a[3] \u003d {2, x+1, 4};\n if(a[1] \u003e 2) reach_error();\n }int x;\n int a[3] \u003d {2, x+1, 4};\n if(a[1] \u003e 2) reach_error();int x;int a[3] \u003d {2, x+1, 4};int a[3] \u003d {2, x+1, 4};int a[3] \u003d {2, x+1, 4};int a[3] \u003d {2, x+1, 4};int a[3] \u003d {2, x+1, 4};int a[3] \u003d {2, x+1, 4};int a[3] \u003d {2, x+1, 4};if(a[1] \u003e 2) reach_error();if(a[1] \u003e 2) reach_error();if(a[1] \u003e 2) reach_error();" + } } }, { - "source": "__loc_1008", + "source": "__loc_991", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -176,17 +334,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 6, - "colNumberStop": 14, - "offsetStart": 81, - "offsetEnd": 88, - "sourceText": "a[1] \u003e 2" + "colNumberStop": 30, + "offsetStart": 78, + "offsetEnd": 104, + "sourceText": "if(a[1] \u003e 2) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003e (read main::a 1) 2) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003e (deref 1 1 Int) 2) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 30, + "offsetStart": 78, + "offsetEnd": 104, + "sourceText": "if(a[1] \u003e 2) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/08vararray.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/08vararray.c.json index c929630b33..f003df9841 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/08vararray.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/08vararray.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1016 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1016", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1016", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,25 +108,128 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::x", "type": "Int" }, { "name": "main::a", - "type": "(Array ([Int] -\u003e Int))" + "type": "Int" + }, + { + "name": "call_reach_error_ret67", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1039 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 106, + "sourceText": "int main() {\n int x;\n int a[3] \u003d {1, 2, 3};\n if(a[x] \u003d\u003d 2) reach_error();\n }" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 106, + "sourceText": "int main() {\n int x;\n int a[3] \u003d {1, 2, 3};\n if(a[x] \u003d\u003d 2) reach_error();\n }" + } + } + }, + { + "name": "__loc_1019", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ + { + "source": "__loc_1019", + "target": "main_final", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 31, + "offsetStart": 76, + "offsetEnd": 103, + "sourceText": "if(a[x] \u003d\u003d 2) reach_error();" + } + }, + "content": "((assume (\u003d (ite (\u003d (deref 1 (mod main::x 18446744073709551616) Int) 2) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 31, + "offsetStart": 22, + "offsetEnd": 106, + "sourceText": "if(a[x] \u003d\u003d 2) reach_error();if(a[x] \u003d\u003d 2) reach_error();int main() {\n int x;\n int a[3] \u003d {1, 2, 3};\n if(a[x] \u003d\u003d 2) reach_error();\n }" + } + } + }, { "source": "main_init", - "target": "__loc_1039", + "target": "__loc_1019", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -96,21 +237,23 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign main::a 1)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::x -2147483648) (\u003c\u003d main::x 2147483647)))" + "content": "((assume (and (\u003e\u003d main::x -2147483648) (\u003c\u003d main::x 2147483647))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -126,42 +269,57 @@ "sourceText": "int a[3] \u003d {1, 2, 3};" } }, - "content": "(assign main::a (array (0 1) (1 2) (2 3) (default 0)))" - } - ] - } - }, - { - "source": "__loc_1039", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(memassign (deref 1 0 Int) 1)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, - "colNumberStart": 7, - "lineNumberStop": 6, - "colNumberStop": 15, - "offsetStart": 79, - "offsetEnd": 87, - "sourceText": "a[x] \u003d\u003d 2" + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 5, + "colNumberStop": 24, + "offsetStart": 50, + "offsetEnd": 70, + "sourceText": "int a[3] \u003d {1, 2, 3};" + } + }, + "content": "(memassign (deref 1 1 Int) 2)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 5, + "colNumberStop": 24, + "offsetStart": 50, + "offsetEnd": 70, + "sourceText": "int a[3] \u003d {1, 2, 3};" } }, - "content": "(assume (\u003d (ite (\u003d (read main::a main::x) 2) 1 0) 0))" + "content": "(memassign (deref 1 2 Int) 3)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 31, + "offsetStart": 22, + "offsetEnd": 106, + "sourceText": "int main() {\n int x;\n int a[3] \u003d {1, 2, 3};\n if(a[x] \u003d\u003d 2) reach_error();\n }int x;\n int a[3] \u003d {1, 2, 3};\n if(a[x] \u003d\u003d 2) reach_error();int x;int a[3] \u003d {1, 2, 3};int a[3] \u003d {1, 2, 3};int a[3] \u003d {1, 2, 3};int a[3] \u003d {1, 2, 3};int a[3] \u003d {1, 2, 3};int a[3] \u003d {1, 2, 3};int a[3] \u003d {1, 2, 3};if(a[x] \u003d\u003d 2) reach_error();if(a[x] \u003d\u003d 2) reach_error();if(a[x] \u003d\u003d 2) reach_error();" + } } }, { - "source": "__loc_1039", + "source": "__loc_1019", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -176,17 +334,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 6, - "colNumberStop": 15, - "offsetStart": 79, - "offsetEnd": 87, - "sourceText": "a[x] \u003d\u003d 2" + "colNumberStop": 31, + "offsetStart": 76, + "offsetEnd": 103, + "sourceText": "if(a[x] \u003d\u003d 2) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003d (read main::a main::x) 2) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003d (deref 1 (mod main::x 18446744073709551616) Int) 2) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 31, + "offsetStart": 76, + "offsetEnd": 103, + "sourceText": "if(a[x] \u003d\u003d 2) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/13typedef.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/13typedef.c.json index 33aaa57d11..d4c39d9886 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/13typedef.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/13typedef.c.json @@ -28,27 +28,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1047 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1047", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1047", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -57,6 +83,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -79,21 +117,83 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::char2", "type": "Int" + }, + { + "name": "call_reach_error_ret68", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1059 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 1, + "offsetStart": 35, + "offsetEnd": 108, + "sourceText": "int main() {\n char char2;\n if(char1 + char2 \u003e 256) reach_error();\n }" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 1, + "offsetStart": 35, + "offsetEnd": 108, + "sourceText": "int main() {\n char char2;\n if(char1 + char2 \u003e 256) reach_error();\n }" + } + } + }, + { + "name": "__loc_1040", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "main_init", - "target": "__loc_1059", + "source": "__loc_1040", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -101,36 +201,40 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "content": "(assign char1 0)" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 7, + "colNumberStart": 4, + "lineNumberStop": 7, + "colNumberStop": 41, + "offsetStart": 68, + "offsetEnd": 105, + "sourceText": "if(char1 + char2 \u003e 256) reach_error();" } }, - "content": "(assume (and (\u003e\u003d main::char2 -128) (\u003c\u003d main::char2 127)))" + "content": "((assume (\u003d (ite (\u003e main::char2 256) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 41, + "offsetStart": 35, + "offsetEnd": 108, + "sourceText": "if(char1 + char2 \u003e 256) reach_error();if(char1 + char2 \u003e 256) reach_error();int main() {\n char char2;\n if(char1 + char2 \u003e 256) reach_error();\n }" + } } }, { - "source": "__loc_1059", - "target": "main_final", + "source": "main_init", + "target": "__loc_1040", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -138,27 +242,41 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign char1 0)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 7, - "colNumberStart": 7, - "lineNumberStop": 7, - "colNumberStop": 25, - "offsetStart": 71, - "offsetEnd": 89, - "sourceText": "char1 + char2 \u003e 256" + "sourceText": "" } }, - "content": "(assume (\u003d (ite (\u003e (+ char1 main::char2) 256) 1 0) 0))" + "content": "((assume (and (\u003e\u003d main::char2 -128) (\u003c\u003d main::char2 127))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 41, + "offsetStart": 35, + "offsetEnd": 108, + "sourceText": "int main() {\n char char2;\n if(char1 + char2 \u003e 256) reach_error();\n }char char2;\n if(char1 + char2 \u003e 256) reach_error();char char2;if(char1 + char2 \u003e 256) reach_error();if(char1 + char2 \u003e 256) reach_error();if(char1 + char2 \u003e 256) reach_error();" + } } }, { - "source": "__loc_1059", + "source": "__loc_1040", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -173,17 +291,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 7, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 7, - "colNumberStop": 25, - "offsetStart": 71, - "offsetEnd": 89, - "sourceText": "char1 + char2 \u003e 256" + "colNumberStop": 41, + "offsetStart": 68, + "offsetEnd": 105, + "sourceText": "if(char1 + char2 \u003e 256) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003e (+ char1 main::char2) 256) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003e main::char2 256) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 7, + "colNumberStart": 4, + "lineNumberStop": 7, + "colNumberStop": 41, + "offsetStart": 68, + "offsetEnd": 105, + "sourceText": "if(char1 + char2 \u003e 256) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/14ushort.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/14ushort.c.json index 2b48af65aa..24be2ad3d9 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/14ushort.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/14ushort.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1067 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1067", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1067", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,6 +108,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::ush", "type": "Int" @@ -81,17 +123,75 @@ { "name": "call___VERIFIER_nondet_ushort_ret69", "type": "Int" + }, + { + "name": "call_reach_error_ret70", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1092 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 10, + "colNumberStop": 1, + "offsetStart": 73, + "offsetEnd": 179, + "sourceText": "int main() {\n short ush;\n long c;\n ush \u003d __VERIFIER_nondet_ushort();\n if(ush) reach_error();\n }" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 10, + "colNumberStop": 1, + "offsetStart": 73, + "offsetEnd": 179, + "sourceText": "int main() {\n short ush;\n long c;\n ush \u003d __VERIFIER_nondet_ushort();\n if(ush) reach_error();\n }" + } + } + }, + { + "name": "__loc_1073", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_1092", + "source": "__loc_1073", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -106,21 +206,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 9, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 9, - "colNumberStop": 9, - "offsetStart": 158, - "offsetEnd": 160, - "sourceText": "ush" + "colNumberStop": 25, + "offsetStart": 155, + "offsetEnd": 176, + "sourceText": "if(ush) reach_error();" } }, - "content": "(assume (\u003d main::ush 0))" + "content": "((assume (\u003d main::ush 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 0, + "lineNumberStop": 10, + "colNumberStop": 25, + "offsetStart": 73, + "offsetEnd": 179, + "sourceText": "if(ush) reach_error();if(ush) reach_error();int main() {\n short ush;\n long c;\n ush \u003d __VERIFIER_nondet_ushort();\n if(ush) reach_error();\n }" + } } }, { - "source": "__loc_1092", + "source": "__loc_1073", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -135,22 +247,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 9, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 9, - "colNumberStop": 9, - "offsetStart": 158, - "offsetEnd": 160, - "sourceText": "ush" + "colNumberStop": 25, + "offsetStart": 155, + "offsetEnd": 176, + "sourceText": "if(ush) reach_error();" } }, - "content": "(assume (/\u003d main::ush 0))" + "content": "((assume (/\u003d main::ush 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 4, + "lineNumberStop": 9, + "colNumberStop": 25, + "offsetStart": 155, + "offsetEnd": 176, + "sourceText": "if(ush) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { "source": "main_init", - "target": "__loc_1092", + "target": "__loc_1073", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -163,32 +287,20 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::ush -32768) (\u003c\u003d main::ush 32767)))" + "content": "((assume (and (\u003e\u003d main::ush -32768) (\u003c\u003d main::ush 32767))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::c -2147483648) (\u003c\u003d main::c 2147483647)))" + "content": "((assume (and (\u003e\u003d main::c -9223372036854775808) (\u003c\u003d main::c 9223372036854775807))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -196,12 +308,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 8, - "colNumberStart": 10, + "colNumberStart": 4, "lineNumberStop": 8, - "colNumberStop": 35, - "offsetStart": 123, - "offsetEnd": 148, - "sourceText": "__VERIFIER_nondet_ushort()" + "colNumberStop": 36, + "offsetStart": 117, + "offsetEnd": 149, + "sourceText": "ush \u003d __VERIFIER_nondet_ushort();" } }, "content": "(havoc call___VERIFIER_nondet_ushort_ret69)" @@ -212,12 +324,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 8, - "colNumberStart": 10, + "colNumberStart": 4, "lineNumberStop": 8, - "colNumberStop": 35, - "offsetStart": 123, - "offsetEnd": 148, - "sourceText": "__VERIFIER_nondet_ushort()" + "colNumberStop": 36, + "offsetStart": 117, + "offsetEnd": 149, + "sourceText": "ush \u003d __VERIFIER_nondet_ushort();" } }, "content": "(assume (and (\u003e\u003d call___VERIFIER_nondet_ushort_ret69 0) (\u003c\u003d call___VERIFIER_nondet_ushort_ret69 65535)))" @@ -227,18 +339,24 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, "content": "(assign main::ush (ite (\u003e\u003d call___VERIFIER_nondet_ushort_ret69 32768) (- call___VERIFIER_nondet_ushort_ret69 65536) call___VERIFIER_nondet_ushort_ret69))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 10, + "colNumberStop": 36, + "offsetStart": 0, + "offsetEnd": 179, + "sourceText": "int main() {\n short ush;\n long c;\n ush \u003d __VERIFIER_nondet_ushort();\n if(ush) reach_error();\n }short ush;\n long c;\n ush \u003d __VERIFIER_nondet_ushort();\n if(ush) reach_error();short ush;long c;ush \u003d __VERIFIER_nondet_ushort();ush \u003d __VERIFIER_nondet_ushort();ush \u003d __VERIFIER_nondet_ushort();ush \u003d __VERIFIER_nondet_ushort();ush \u003d __VERIFIER_nondet_ushort();if(ush) reach_error();if(ush) reach_error();if(ush) reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/15addition.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/15addition.c.json index 6f03c3bd8a..32cdf83e21 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/15addition.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/15addition.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1100 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1100", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1100", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,6 +108,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::z", "type": "Int" @@ -77,18 +119,64 @@ { "name": "main::y", "type": "Int" + }, + { + "name": "call_reach_error_ret71", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1124 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 122, + "sourceText": "int main() {\n int z \u003d 6;\n int y \u003d 1;\n if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();\n }" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 122, + "sourceText": "int main() {\n int z \u003d 6;\n int y \u003d 1;\n if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();\n }" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { "source": "main_init", - "target": "__loc_1124", + "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -129,64 +217,18 @@ "content": "(assign main::y 1)" } ] - } - }, - { - "source": "__loc_1124", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 6, - "colNumberStart": 7, - "lineNumberStop": 6, - "colNumberStop": 38, - "offsetStart": 72, - "offsetEnd": 103, - "sourceText": "(z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0" - } - }, - "content": "(assume (\u003d (ite (\u003d (+ (* main::z main::z) (- (* 12 main::y)) (- (* 6 main::z)) 12) 0) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_1124", - "target": "main_error", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 6, - "colNumberStart": 7, - "lineNumberStop": 6, - "colNumberStop": 38, - "offsetStart": 72, - "offsetEnd": 103, - "sourceText": "(z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0" - } - }, - "content": "(assume (/\u003d (ite (\u003d (+ (* main::z main::z) (- (* 12 main::y)) (- (* 6 main::z)) 12) 0) 1 0) 0))" - } - ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 54, + "offsetStart": 22, + "offsetEnd": 122, + "sourceText": "int main() {\n int z \u003d 6;\n int y \u003d 1;\n if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();\n }int z \u003d 6;\n int y \u003d 1;\n if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();int z \u003d 6;int z \u003d 6;int z \u003d 6;int z \u003d 6;int y \u003d 1;int y \u003d 1;int y \u003d 1;int y \u003d 1;if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();if((z*z) - 12 * y - 6 * z + 12 \u003d\u003d 0) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/16loop.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/16loop.c.json index 3836651878..19fc82d605 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/16loop.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/16loop.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1132 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1132", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1132", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -70,22 +108,95 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::for0::i", "type": "Int" + }, + { + "name": "call_reach_error_ret72", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1147 ", - "__loc_1156 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 111, + "sourceText": "int main() {\n for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }\n }" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 1, + "offsetStart": 22, + "offsetEnd": 111, + "sourceText": "int main() {\n for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }\n }" + } + } + }, + { + "name": "__loc_1132", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1141", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_1147", - "target": "__loc_1156", + "source": "__loc_1132", + "target": "__loc_1141", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -99,22 +210,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 19, - "lineNumberStop": 4, - "colNumberStop": 24, - "offsetStart": 54, - "offsetEnd": 59, - "sourceText": "i \u003c 30" + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 4, + "offsetStart": 39, + "offsetEnd": 108, + "sourceText": "for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }" } }, - "content": "(assume (/\u003d (ite (\u003c main::for0::i 30) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003c main::for0::i 30) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 33, + "offsetStart": 39, + "offsetEnd": 108, + "sourceText": "for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }{\n if(i \u003d\u003d 28) reach_error();\n }if(i \u003d\u003d 28) reach_error();if(i \u003d\u003d 28) reach_error();if(i \u003d\u003d 28) reach_error();" + } } }, { - "source": "__loc_1147", - "target": "main_final", + "source": "__loc_1141", + "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -127,23 +250,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 19, - "lineNumberStop": 4, - "colNumberStop": 24, - "offsetStart": 54, - "offsetEnd": 59, - "sourceText": "i \u003c 30" + "lineNumberStart": 5, + "colNumberStart": 8, + "lineNumberStop": 5, + "colNumberStop": 33, + "offsetStart": 77, + "offsetEnd": 102, + "sourceText": "if(i \u003d\u003d 28) reach_error();" } }, - "content": "(assume (\u003d (ite (\u003c main::for0::i 30) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003d main::for0::i 28) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 8, + "lineNumberStop": 5, + "colNumberStop": 33, + "offsetStart": 77, + "offsetEnd": 102, + "sourceText": "if(i \u003d\u003d 28) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { - "source": "main_init", - "target": "__loc_1147", + "source": "__loc_1132", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -157,22 +292,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 8, - "lineNumberStop": 4, - "colNumberStop": 16, - "offsetStart": 43, - "offsetEnd": 51, - "sourceText": "int i \u003d 0" + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 4, + "offsetStart": 39, + "offsetEnd": 108, + "sourceText": "for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }" } }, - "content": "(assign main::for0::i 0)" + "content": "((assume (\u003d (ite (\u003c main::for0::i 30) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 4, + "offsetStart": 22, + "offsetEnd": 111, + "sourceText": "for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }int main() {\n for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }\n }" + } } }, { - "source": "__loc_1156", - "target": "main_error", + "source": "main_init", + "target": "__loc_1132", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -185,23 +332,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 5, - "colNumberStart": 11, - "lineNumberStop": 5, - "colNumberStop": 17, - "offsetStart": 80, - "offsetEnd": 86, - "sourceText": "i \u003d\u003d 28" + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 4, + "offsetStart": 39, + "offsetEnd": 108, + "sourceText": "for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }" } }, - "content": "(assume (/\u003d (ite (\u003d main::for0::i 28) 1 0) 0))" + "content": "(assign main::for0::i 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 4, + "offsetStart": 22, + "offsetEnd": 111, + "sourceText": "int main() {\n for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }" + } } }, { - "source": "__loc_1156", - "target": "__loc_1147", + "source": "__loc_1141", + "target": "__loc_1132", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -215,15 +374,15 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 5, - "colNumberStart": 11, + "colNumberStart": 8, "lineNumberStop": 5, - "colNumberStop": 17, - "offsetStart": 80, - "offsetEnd": 86, - "sourceText": "i \u003d\u003d 28" + "colNumberStop": 33, + "offsetStart": 77, + "offsetEnd": 102, + "sourceText": "if(i \u003d\u003d 28) reach_error();" } }, - "content": "(assume (\u003d (ite (\u003d main::for0::i 28) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003d main::for0::i 28) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", @@ -231,17 +390,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 27, - "lineNumberStop": 4, - "colNumberStop": 29, - "offsetStart": 62, - "offsetEnd": 64, - "sourceText": "i++" + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 4, + "offsetStart": 39, + "offsetEnd": 108, + "sourceText": "for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }" } }, "content": "(assign main::for0::i (+ main::for0::i 1))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 33, + "offsetStart": 39, + "offsetEnd": 108, + "sourceText": "if(i \u003d\u003d 28) reach_error();if(i \u003d\u003d 28) reach_error();for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }for(int i \u003d 0; i \u003c 30; i++) {\n if(i \u003d\u003d 28) reach_error();\n }" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/17recursive.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/17recursive.c.json index 9b4a16a997..beaed45bc9 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/17recursive.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/17recursive.c.json @@ -19,27 +19,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1171 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1171", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1171", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,6 +74,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -84,11 +122,11 @@ ], "vars": [ { - "name": "fibonacci::i", + "name": "fibonacci_ret", "type": "Int" }, { - "name": "fibonacci_ret", + "name": "fibonacci::i", "type": "Int" }, { @@ -101,32 +139,131 @@ } ], "locs": [ - "fibonacci_init {init}", - "fibonacci_final {final}", - "__loc_1179 ", - "__loc_1185 ", - "__loc_1194 ", - "__loc_1200 ", - "__loc_1211 ", - "__loc_1216 ", - "__loc_1217 " - ], - "edges": [ { - "source": "fibonacci_init", - "target": "__loc_1179", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "fibonacci_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 22, + "offsetEnd": 149, + "sourceText": "int fibonacci(int i) {\n if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);\n}" + } } }, { - "source": "__loc_1211", - "target": "__loc_1216", + "name": "fibonacci_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 22, + "offsetEnd": 149, + "sourceText": "int fibonacci(int i) {\n if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);\n}" + } + } + }, + { + "name": "__loc_1166", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1181", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1195", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" + } + } + }, + { + "name": "__loc_1198", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1200", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" + } + } + }, + { + "name": "__loc_1203", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + } + ], + "edges": [ + { + "source": "__loc_1198", + "target": "__loc_1195", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -140,22 +277,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 16, + "colNumberStart": 9, "lineNumberStop": 6, - "colNumberStop": 29, - "offsetStart": 116, - "offsetEnd": 129, - "sourceText": "fibonacci(i-1)" + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" } }, - "content": "fibonacci(call_fibonacci_ret73, (+ (+ (+ fibonacci::i) (+ (- 1)))))" + "content": "fibonacci(call_fibonacci_ret73, (+ (+ (+ fibonacci::i) (- (+ 1)))))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" + } } }, { - "source": "__loc_1216", - "target": "__loc_1217", + "source": "__loc_1203", + "target": "__loc_1200", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -169,21 +318,57 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 33, + "colNumberStart": 9, "lineNumberStop": 6, - "colNumberStop": 46, - "offsetStart": 133, - "offsetEnd": 146, - "sourceText": "fibonacci(i-2)" + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" } }, - "content": "fibonacci(call_fibonacci_ret74, (+ (+ (+ fibonacci::i) (+ (- 2)))))" + "content": "fibonacci(call_fibonacci_ret74, (+ (+ (+ fibonacci::i) (- (+ 2)))))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" + } + } + }, + { + "source": "fibonacci_init", + "target": "__loc_1166", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 47, + "offsetStart": 22, + "offsetEnd": 149, + "sourceText": "int fibonacci(int i) {\n if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);\n}if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);" + } } }, { - "source": "__loc_1185", + "source": "__loc_1166", "target": "fibonacci_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -192,6 +377,22 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 49, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);" + } + }, + "content": "((assume (/\u003d (ite (\u003d fibonacci::i 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -200,20 +401,32 @@ "lineNumberStart": 4, "colNumberStart": 15, "lineNumberStop": 4, - "colNumberStop": 22, + "colNumberStop": 23, "offsetStart": 60, - "offsetEnd": 67, - "sourceText": "return 0" + "offsetEnd": 68, + "sourceText": "return 0;" } }, "content": "(assign fibonacci_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 49, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);return 0;return 0;return 0;return 0;" + } } }, { - "source": "__loc_1200", - "target": "fibonacci_final", + "source": "__loc_1166", + "target": "__loc_1181", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -226,22 +439,34 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 5, - "colNumberStart": 20, - "lineNumberStop": 5, - "colNumberStop": 27, - "offsetStart": 90, - "offsetEnd": 97, - "sourceText": "return 1" + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 49, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);" } }, - "content": "(assign fibonacci_ret 1)" + "content": "((assume (\u003d (ite (\u003d fibonacci::i 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 4, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 49, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 0) return 0;\n else if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);" + } } }, { - "source": "__loc_1217", + "source": "__loc_1181", "target": "fibonacci_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -255,52 +480,51 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, + "lineNumberStart": 5, "colNumberStart": 9, "lineNumberStop": 6, - "colNumberStop": 46, - "offsetStart": 109, - "offsetEnd": 146, - "sourceText": "return fibonacci(i-1) + fibonacci(i-2)" + "colNumberStop": 47, + "offsetStart": 79, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);" } }, - "content": "(assign fibonacci_ret (+ call_fibonacci_ret73 call_fibonacci_ret74))" - } - ] - } - }, - { - "source": "__loc_1179", - "target": "__loc_1185", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "((assume (/\u003d (ite (\u003d fibonacci::i 1) 1 0) 0)))[choiceType\u003dMAIN_PATH]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 12, - "offsetStart": 52, - "offsetEnd": 57, - "sourceText": "i \u003d\u003d 0" + "lineNumberStart": 5, + "colNumberStart": 20, + "lineNumberStop": 5, + "colNumberStop": 28, + "offsetStart": 90, + "offsetEnd": 98, + "sourceText": "return 1;" } }, - "content": "(assume (/\u003d (ite (\u003d fibonacci::i 0) 1 0) 0))" + "content": "(assign fibonacci_ret 1)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 79, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);return 1;return 1;return 1;return 1;" + } } }, { - "source": "__loc_1179", - "target": "__loc_1194", + "source": "__loc_1181", + "target": "__loc_1198", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -313,52 +537,59 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 12, - "offsetStart": 52, - "offsetEnd": 57, - "sourceText": "i \u003d\u003d 0" + "lineNumberStart": 5, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 79, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);" } }, - "content": "(assume (\u003d (ite (\u003d fibonacci::i 0) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003d fibonacci::i 1) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 79, + "offsetEnd": 147, + "sourceText": "if(i \u003d\u003d 1) return 1;\n else return fibonacci(i-1) + fibonacci(i-2);return fibonacci(i-1) + fibonacci(i-2);return fibonacci(i-1) + fibonacci(i-2);return fibonacci(i-1) + fibonacci(i-2);return fibonacci(i-1) + fibonacci(i-2);return fibonacci(i-1) + fibonacci(i-2);" + } } }, { - "source": "__loc_1194", - "target": "__loc_1200", + "source": "__loc_1195", + "target": "__loc_1203", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", "content": {} }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 5, - "colNumberStart": 12, - "lineNumberStop": 5, - "colNumberStop": 17, - "offsetStart": 82, - "offsetEnd": 87, - "sourceText": "i \u003d\u003d 1" - } - }, - "content": "(assume (/\u003d (ite (\u003d fibonacci::i 1) 1 0) 0))" - } - ] + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);return fibonacci(i-1) + fibonacci(i-2);" + } } }, { - "source": "__loc_1194", - "target": "__loc_1211", + "source": "__loc_1200", + "target": "fibonacci_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -371,18 +602,30 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 5, - "colNumberStart": 12, - "lineNumberStop": 5, - "colNumberStop": 17, - "offsetStart": 82, - "offsetEnd": 87, - "sourceText": "i \u003d\u003d 1" + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" } }, - "content": "(assume (\u003d (ite (\u003d fibonacci::i 1) 1 0) 0))" + "content": "(assign fibonacci_ret (+ call_fibonacci_ret73 call_fibonacci_ret74))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 9, + "lineNumberStop": 6, + "colNumberStop": 47, + "offsetStart": 109, + "offsetEnd": 147, + "sourceText": "return fibonacci(i-1) + fibonacci(i-2);" + } } } ] @@ -405,22 +648,101 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "call_fibonacci_ret75", "type": "Int" + }, + { + "name": "call_reach_error_ret76", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1228 ", - "__loc_1231 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 0, + "offsetStart": 152, + "offsetEnd": 207, + "sourceText": "int main() {\n if(fibonacci(8) !\u003d 21) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 0, + "offsetStart": 152, + "offsetEnd": 207, + "sourceText": "int main() {\n if(fibonacci(8) !\u003d 21) reach_error();\n}" + } + } + }, + { + "name": "__loc_1216", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 4, + "lineNumberStop": 10, + "colNumberStop": 40, + "offsetStart": 169, + "offsetEnd": 205, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();" + } + } + }, + { + "name": "__loc_1219", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_1231", - "target": "__loc_1228", + "source": "__loc_1219", + "target": "__loc_1216", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -434,33 +756,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 10, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 10, - "colNumberStop": 18, - "offsetStart": 172, - "offsetEnd": 183, - "sourceText": "fibonacci(8)" + "colNumberStop": 40, + "offsetStart": 169, + "offsetEnd": 205, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();" } }, "content": "fibonacci(call_fibonacci_ret75, 8)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 4, + "lineNumberStop": 10, + "colNumberStop": 40, + "offsetStart": 169, + "offsetEnd": 205, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();" + } } }, { - "source": "main_init", - "target": "__loc_1231", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] - } - }, - { - "source": "__loc_1228", + "source": "__loc_1216", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -475,21 +797,57 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 10, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 10, - "colNumberStop": 24, - "offsetStart": 172, - "offsetEnd": 189, - "sourceText": "fibonacci(8) !\u003d 21" + "colNumberStop": 40, + "offsetStart": 169, + "offsetEnd": 205, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();" } }, - "content": "(assume (\u003d (ite (/\u003d call_fibonacci_ret75 21) 1 0) 0))" + "content": "((assume (\u003d (ite (/\u003d call_fibonacci_ret75 21) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 40, + "offsetStart": 152, + "offsetEnd": 207, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();if(fibonacci(8) !\u003d 21) reach_error();int main() {\n if(fibonacci(8) !\u003d 21) reach_error();\n}" + } } }, { - "source": "__loc_1228", + "source": "main_init", + "target": "__loc_1219", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 40, + "offsetStart": 152, + "offsetEnd": 207, + "sourceText": "int main() {\n if(fibonacci(8) !\u003d 21) reach_error();\n}if(fibonacci(8) !\u003d 21) reach_error();if(fibonacci(8) !\u003d 21) reach_error();if(fibonacci(8) !\u003d 21) reach_error();if(fibonacci(8) !\u003d 21) reach_error();if(fibonacci(8) !\u003d 21) reach_error();if(fibonacci(8) !\u003d 21) reach_error();" + } + } + }, + { + "source": "__loc_1216", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -504,17 +862,29 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 10, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 10, - "colNumberStop": 24, - "offsetStart": 172, - "offsetEnd": 189, - "sourceText": "fibonacci(8) !\u003d 21" + "colNumberStop": 40, + "offsetStart": 169, + "offsetEnd": 205, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();" } }, - "content": "(assume (/\u003d (ite (/\u003d call_fibonacci_ret75 21) 1 0) 0))" + "content": "((assume (/\u003d (ite (/\u003d call_fibonacci_ret75 21) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 4, + "lineNumberStop": 10, + "colNumberStop": 40, + "offsetStart": 169, + "offsetEnd": 205, + "sourceText": "if(fibonacci(8) !\u003d 21) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/18multithread.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/18multithread.c.json index a349cae1e8..06e194a4dc 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/18multithread.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/18multithread.c.json @@ -36,27 +36,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1239 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1239", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 687, + "colNumberStart": 0, + "lineNumberStop": 687, + "colNumberStop": 19, + "offsetStart": 29546, + "offsetEnd": 29565, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1239", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 687, + "colNumberStart": 0, + "lineNumberStop": 687, + "colNumberStop": 19, + "offsetStart": 29546, + "offsetEnd": 29565, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -65,6 +91,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 687, + "colNumberStart": 0, + "lineNumberStop": 687, + "colNumberStop": 19, + "offsetStart": 29546, + "offsetEnd": 29565, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -99,34 +137,110 @@ } } ], - "vars": [], - "locs": [ - "thr1_init {init}", - "thr1_final {final}", - "__loc_1244 ", - "__loc_1254 ", - "__loc_1259 ", - "__loc_1265 ", - "__loc_1275 ", - "__loc_1280 ", - "__loc_1282 " + "vars": [ + { + "name": "thr1_ret", + "type": "Int" + }, + { + "name": "thr1::_", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret77", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret78", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret79", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret80", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "__loc_1282", - "target": "thr1_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "thr1_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 695, + "colNumberStart": 0, + "lineNumberStop": 702, + "colNumberStop": 0, + "offsetStart": 29670, + "offsetEnd": 29834, + "sourceText": "void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n x \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n x \u003d 2;\n __VERIFIER_atomic_end();\n}" + } } }, + { + "name": "thr1_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 695, + "colNumberStart": 0, + "lineNumberStop": 702, + "colNumberStop": 0, + "offsetStart": 29670, + "offsetEnd": 29834, + "sourceText": "void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n x \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n x \u003d 2;\n __VERIFIER_atomic_end();\n}" + } + } + }, + { + "name": "__loc_1234", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 696, + "colNumberStart": 4, + "lineNumberStop": 696, + "colNumberStop": 29, + "offsetStart": 29696, + "offsetEnd": 29721, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_1253", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 699, + "colNumberStart": 4, + "lineNumberStop": 699, + "colNumberStop": 29, + "offsetStart": 29767, + "offsetEnd": 29792, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + } + ], + "edges": [ { "source": "thr1_init", - "target": "__loc_1244", + "target": "__loc_1234", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -134,11 +248,23 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 695, + "colNumberStart": 0, + "lineNumberStop": 702, + "colNumberStop": 29, + "offsetStart": 29670, + "offsetEnd": 29834, + "sourceText": "void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n x \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n x \u003d 2;\n __VERIFIER_atomic_end();\n}__VERIFIER_atomic_begin();\n x \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n x \u003d 2;\n __VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_1254", - "target": "__loc_1259", + "source": "__loc_1234", + "target": "__loc_1253", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -147,85 +273,65 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 696, + "colNumberStart": 4, + "lineNumberStop": 696, + "colNumberStop": 29, + "offsetStart": 29696, + "offsetEnd": 29721, + "sourceText": "__VERIFIER_atomic_begin();" } }, - "content": "(assign x 1)" - } - ] - } - }, - { - "source": "__loc_1275", - "target": "__loc_1280", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "F[ATOMIC_BEGIN]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign x 2)" - } - ] - } - }, - { - "source": "__loc_1244", - "target": "__loc_1254", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign x 1)" + }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 693, + "lineNumberStart": 698, "colNumberStart": 4, - "lineNumberStop": 693, - "colNumberStop": 28, - "offsetStart": 29619, - "offsetEnd": 29643, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStop": 698, + "colNumberStop": 27, + "offsetStart": 29738, + "offsetEnd": 29761, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "F[ATOMIC_BEGIN]" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 696, + "colNumberStart": 4, + "lineNumberStop": 699, + "colNumberStop": 29, + "offsetStart": 29696, + "offsetEnd": 29792, + "sourceText": "__VERIFIER_atomic_begin();x \u003d 1;x \u003d 1;x \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_1259", - "target": "__loc_1265", + "source": "__loc_1253", + "target": "thr1_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -238,76 +344,56 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 695, + "lineNumberStart": 699, "colNumberStart": 4, - "lineNumberStop": 695, - "colNumberStop": 26, - "offsetStart": 29661, - "offsetEnd": 29683, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStop": 699, + "colNumberStop": 29, + "offsetStart": 29767, + "offsetEnd": 29792, + "sourceText": "__VERIFIER_atomic_begin();" } }, - "content": "F[ATOMIC_END]" - } - ] - } - }, - { - "source": "__loc_1265", - "target": "__loc_1275", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "F[ATOMIC_BEGIN]" + }, { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 696, - "colNumberStart": 4, - "lineNumberStop": 696, - "colNumberStop": 28, - "offsetStart": 29690, - "offsetEnd": 29714, - "sourceText": "__VERIFIER_atomic_begin()" + "sourceText": "" } }, - "content": "F[ATOMIC_BEGIN]" - } - ] - } - }, - { - "source": "__loc_1280", - "target": "__loc_1282", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign x 2)" + }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 698, + "lineNumberStart": 701, "colNumberStart": 4, - "lineNumberStop": 698, - "colNumberStop": 26, - "offsetStart": 29732, - "offsetEnd": 29754, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStop": 701, + "colNumberStop": 27, + "offsetStart": 29809, + "offsetEnd": 29832, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 695, + "colNumberStart": 0, + "lineNumberStop": 702, + "colNumberStop": 29, + "offsetStart": 29670, + "offsetEnd": 29834, + "sourceText": "__VERIFIER_atomic_begin();x \u003d 2;x \u003d 2;x \u003d 2;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n x \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n x \u003d 2;\n __VERIFIER_atomic_end();\n}" + } } } ] @@ -343,6 +429,14 @@ } ], "vars": [ + { + "name": "thr2_ret", + "type": "Int" + }, + { + "name": "thr2::_", + "type": "Int" + }, { "name": "thr2::i", "type": "Int" @@ -350,37 +444,132 @@ { "name": "thr2::j", "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret81", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret82", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret83", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret84", + "type": "Int" } ], "locs": [ - "thr2_init {init}", - "thr2_final {final}", - "__loc_1287 ", - "__loc_1295 ", - "__loc_1299 ", - "__loc_1305 ", - "__loc_1313 ", - "__loc_1317 ", - "__loc_1321 ", - "__loc_1326 ", - "__loc_1335 " - ], - "edges": [ { - "source": "__loc_1321", - "target": "thr2_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "thr2_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 704, + "colNumberStart": 0, + "lineNumberStop": 712, + "colNumberStop": 0, + "offsetStart": 29837, + "offsetEnd": 30033, + "sourceText": "void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n int i \u003d x;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int j \u003d x;\n __VERIFIER_atomic_end();\n if(i !\u003d j) ERR \u003d 1;\n}" + } + } + }, + { + "name": "thr2_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 704, + "colNumberStart": 0, + "lineNumberStop": 712, + "colNumberStop": 0, + "offsetStart": 29837, + "offsetEnd": 30033, + "sourceText": "void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n int i \u003d x;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int j \u003d x;\n __VERIFIER_atomic_end();\n if(i !\u003d j) ERR \u003d 1;\n}" + } } }, + { + "name": "__loc_1274", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 705, + "colNumberStart": 4, + "lineNumberStop": 705, + "colNumberStop": 29, + "offsetStart": 29863, + "offsetEnd": 29888, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_1292", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 708, + "colNumberStart": 4, + "lineNumberStop": 708, + "colNumberStop": 29, + "offsetStart": 29938, + "offsetEnd": 29963, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_1313", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1320", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 711, + "colNumberStart": 15, + "lineNumberStop": 711, + "colNumberStop": 22, + "offsetStart": 30024, + "offsetEnd": 30031, + "sourceText": "ERR \u003d 1;" + } + } + } + ], + "edges": [ { "source": "thr2_init", - "target": "__loc_1287", + "target": "__loc_1274", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -388,11 +577,23 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 704, + "colNumberStart": 0, + "lineNumberStop": 712, + "colNumberStop": 29, + "offsetStart": 29837, + "offsetEnd": 30033, + "sourceText": "void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n int i \u003d x;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int j \u003d x;\n __VERIFIER_atomic_end();\n if(i !\u003d j) ERR \u003d 1;\n}__VERIFIER_atomic_begin();\n int i \u003d x;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int j \u003d x;\n __VERIFIER_atomic_end();\n if(i !\u003d j) ERR \u003d 1;__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_1295", - "target": "__loc_1299", + "source": "__loc_1274", + "target": "__loc_1292", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -401,34 +602,21 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 703, + "lineNumberStart": 705, "colNumberStart": 4, - "lineNumberStop": 703, - "colNumberStop": 13, - "offsetStart": 29817, - "offsetEnd": 29826, - "sourceText": "int i \u003d x;" + "lineNumberStop": 705, + "colNumberStop": 29, + "offsetStart": 29863, + "offsetEnd": 29888, + "sourceText": "__VERIFIER_atomic_begin();" } }, - "content": "(assign thr2::i x)" - } - ] - } - }, - { - "source": "__loc_1313", - "target": "__loc_1317", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "F[ATOMIC_BEGIN]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -438,48 +626,47 @@ "colNumberStart": 4, "lineNumberStop": 706, "colNumberStop": 13, - "offsetStart": 29892, - "offsetEnd": 29901, - "sourceText": "int j \u003d x;" + "offsetStart": 29894, + "offsetEnd": 29903, + "sourceText": "int i \u003d x;" } }, - "content": "(assign thr2::j x)" - } - ] - } - }, - { - "source": "__loc_1326", - "target": "__loc_1335", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i x)" + }, { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 708, - "colNumberStart": 7, - "lineNumberStop": 708, - "colNumberStop": 12, - "offsetStart": 29939, - "offsetEnd": 29944, - "sourceText": "i !\u003d j" + "lineNumberStart": 707, + "colNumberStart": 4, + "lineNumberStop": 707, + "colNumberStop": 27, + "offsetStart": 29909, + "offsetEnd": 29932, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "(assume (/\u003d (ite (/\u003d thr2::i thr2::j) 1 0) 0))" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 705, + "colNumberStart": 4, + "lineNumberStop": 708, + "colNumberStop": 29, + "offsetStart": 29863, + "offsetEnd": 29963, + "sourceText": "__VERIFIER_atomic_begin();int i \u003d x;int i \u003d x;int i \u003d x;int i \u003d x;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_1326", - "target": "__loc_1321", + "source": "__loc_1292", + "target": "__loc_1313", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -488,85 +675,71 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 708, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 708, - "colNumberStop": 12, - "offsetStart": 29939, - "offsetEnd": 29944, - "sourceText": "i !\u003d j" + "colNumberStop": 29, + "offsetStart": 29938, + "offsetEnd": 29963, + "sourceText": "__VERIFIER_atomic_begin();" } }, - "content": "(assume (\u003d (ite (/\u003d thr2::i thr2::j) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_1335", - "target": "__loc_1321", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "F[ATOMIC_BEGIN]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 709, + "colNumberStart": 4, + "lineNumberStop": 709, + "colNumberStop": 13, + "offsetStart": 29969, + "offsetEnd": 29978, + "sourceText": "int j \u003d x;" } }, - "content": "(assign ERR 1)" - } - ] - } - }, - { - "source": "__loc_1287", - "target": "__loc_1295", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::j x)" + }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 702, + "lineNumberStart": 710, "colNumberStart": 4, - "lineNumberStop": 702, - "colNumberStop": 28, - "offsetStart": 29786, - "offsetEnd": 29810, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStop": 710, + "colNumberStop": 27, + "offsetStart": 29984, + "offsetEnd": 30007, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "F[ATOMIC_BEGIN]" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 708, + "colNumberStart": 4, + "lineNumberStop": 711, + "colNumberStop": 29, + "offsetStart": 29938, + "offsetEnd": 30031, + "sourceText": "__VERIFIER_atomic_begin();int j \u003d x;int j \u003d x;int j \u003d x;int j \u003d x;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();if(i !\u003d j) ERR \u003d 1;if(i !\u003d j) ERR \u003d 1;if(i !\u003d j) ERR \u003d 1;" + } } }, { - "source": "__loc_1299", - "target": "__loc_1305", + "source": "__loc_1313", + "target": "__loc_1320", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -575,27 +748,39 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 704, + "lineNumberStart": 711, "colNumberStart": 4, - "lineNumberStop": 704, - "colNumberStop": 26, - "offsetStart": 29832, - "offsetEnd": 29854, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStop": 711, + "colNumberStop": 22, + "offsetStart": 30013, + "offsetEnd": 30031, + "sourceText": "if(i !\u003d j) ERR \u003d 1;" } }, - "content": "F[ATOMIC_END]" + "content": "((assume (/\u003d (ite (/\u003d thr2::i thr2::j) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 711, + "colNumberStart": 4, + "lineNumberStop": 711, + "colNumberStop": 22, + "offsetStart": 30013, + "offsetEnd": 30031, + "sourceText": "if(i !\u003d j) ERR \u003d 1;ERR \u003d 1;ERR \u003d 1;ERR \u003d 1;" + } } }, { - "source": "__loc_1305", - "target": "__loc_1313", + "source": "__loc_1313", + "target": "thr2_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -604,27 +789,39 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 705, + "lineNumberStart": 711, "colNumberStart": 4, - "lineNumberStop": 705, - "colNumberStop": 28, - "offsetStart": 29861, - "offsetEnd": 29885, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStop": 711, + "colNumberStop": 22, + "offsetStart": 30013, + "offsetEnd": 30031, + "sourceText": "if(i !\u003d j) ERR \u003d 1;" } }, - "content": "F[ATOMIC_BEGIN]" + "content": "((assume (\u003d (ite (/\u003d thr2::i thr2::j) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 704, + "colNumberStart": 0, + "lineNumberStop": 712, + "colNumberStop": 22, + "offsetStart": 29837, + "offsetEnd": 30033, + "sourceText": "if(i !\u003d j) ERR \u003d 1;if(i !\u003d j) ERR \u003d 1;void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n int i \u003d x;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int j \u003d x;\n __VERIFIER_atomic_end();\n if(i !\u003d j) ERR \u003d 1;\n}" + } } }, { - "source": "__loc_1317", - "target": "__loc_1326", + "source": "__loc_1320", + "target": "thr2_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -633,22 +830,28 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 707, - "colNumberStart": 4, - "lineNumberStop": 707, - "colNumberStop": 26, - "offsetStart": 29907, - "offsetEnd": 29929, - "sourceText": "__VERIFIER_atomic_end()" + "sourceText": "" } }, - "content": "F[ATOMIC_END]" + "content": "(assign ERR 1)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 712, + "colNumberStop": 22, + "offsetStart": 0, + "offsetEnd": 30033, + "sourceText": "if(i !\u003d j) ERR \u003d 1;void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n int i \u003d x;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int j \u003d x;\n __VERIFIER_atomic_end();\n if(i !\u003d j) ERR \u003d 1;\n}" + } } } ] @@ -671,6 +874,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::t1", "type": "Int" @@ -680,22 +887,106 @@ "type": "Int" }, { - "name": "main_ret", + "name": "call_pthread_create_ret85", + "type": "Int" + }, + { + "name": "call_pthread_create_ret86", + "type": "Int" + }, + { + "name": "call_reach_error_ret87", "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1360 ", - "__loc_1378 ", - "__loc_1386 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 0, + "lineNumberStop": 720, + "colNumberStop": 0, + "offsetStart": 30036, + "offsetEnd": 30186, + "sourceText": "int main() {\n pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(ERR) reach_error();\n return 0;\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 0, + "lineNumberStop": 720, + "colNumberStop": 0, + "offsetStart": 30036, + "offsetEnd": 30186, + "sourceText": "int main() {\n pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(ERR) reach_error();\n return 0;\n}" + } + } + }, + { + "name": "__loc_1345", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1363", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1371", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_1360", - "target": "__loc_1378", + "source": "main_init", + "target": "__loc_1345", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -704,27 +995,59 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StartLabel", + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign x 0)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign ERR 0)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 713, - "colNumberStart": 4, - "lineNumberStop": 713, - "colNumberStop": 34, - "offsetStart": 29998, - "offsetEnd": 30028, - "sourceText": "pthread_create(\u0026t1, 0, thr1, 0)" + "sourceText": "" + } + }, + "content": "((assume (and (\u003e\u003d main::t1 0) (\u003c\u003d main::t1 18446744073709551615))))[choiceType\u003dMAIN_PATH]" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" } }, - "content": "(var main::t1 Int) \u003d start thr1(0)" + "content": "((assume (and (\u003e\u003d main::t2 0) (\u003c\u003d main::t2 18446744073709551615))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 0, + "lineNumberStop": 720, + "colNumberStop": 35, + "offsetStart": 30036, + "offsetEnd": 30186, + "sourceText": "int main() {\n pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(ERR) reach_error();\n return 0;\n}pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(ERR) reach_error();\n return 0;pthread_t t1, t2;pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);" + } } }, { - "source": "__loc_1378", - "target": "__loc_1386", + "source": "__loc_1345", + "target": "__loc_1363", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -737,23 +1060,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 714, + "lineNumberStart": 716, "colNumberStart": 4, - "lineNumberStop": 714, - "colNumberStop": 34, - "offsetStart": 30035, - "offsetEnd": 30065, - "sourceText": "pthread_create(\u0026t2, 0, thr2, 0)" + "lineNumberStop": 716, + "colNumberStop": 35, + "offsetStart": 30075, + "offsetEnd": 30106, + "sourceText": "pthread_create(\u0026t1, 0, thr1, 0);" } }, - "content": "(var main::t2 Int) \u003d start thr2(0)" + "content": "(var main::t1 Int) \u003d start thr1(0, 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 716, + "colNumberStart": 4, + "lineNumberStop": 717, + "colNumberStop": 35, + "offsetStart": 30075, + "offsetEnd": 30143, + "sourceText": "pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);" + } } }, { - "source": "main_init", - "target": "__loc_1360", + "source": "__loc_1363", + "target": "__loc_1371", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -762,58 +1097,38 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "content": "(assign x 0)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "content": "(assign ERR 0)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" - } - }, - "content": "(assume (and (\u003e\u003d main::t1 0) (\u003c\u003d main::t1 4294967295)))" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.StartLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 717, + "colNumberStart": 4, + "lineNumberStop": 717, + "colNumberStop": 35, + "offsetStart": 30112, + "offsetEnd": 30143, + "sourceText": "pthread_create(\u0026t2, 0, thr2, 0);" } }, - "content": "(assume (and (\u003e\u003d main::t2 0) (\u003c\u003d main::t2 4294967295)))" + "content": "(var main::t2 Int) \u003d start thr2(0, 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 717, + "colNumberStart": 4, + "lineNumberStop": 718, + "colNumberStop": 35, + "offsetStart": 30112, + "offsetEnd": 30170, + "sourceText": "pthread_create(\u0026t2, 0, thr2, 0);if(ERR) reach_error();if(ERR) reach_error();if(ERR) reach_error();" + } } }, { - "source": "__loc_1386", + "source": "__loc_1371", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -827,22 +1142,34 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 715, - "colNumberStart": 7, - "lineNumberStop": 715, - "colNumberStop": 9, - "offsetStart": 30075, - "offsetEnd": 30077, - "sourceText": "ERR" + "lineNumberStart": 718, + "colNumberStart": 4, + "lineNumberStop": 718, + "colNumberStop": 25, + "offsetStart": 30149, + "offsetEnd": 30170, + "sourceText": "if(ERR) reach_error();" } }, - "content": "(assume (/\u003d ERR 0))" + "content": "((assume (/\u003d ERR 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 718, + "colNumberStart": 4, + "lineNumberStop": 718, + "colNumberStop": 25, + "offsetStart": 30149, + "offsetEnd": 30170, + "sourceText": "if(ERR) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { - "source": "__loc_1386", + "source": "__loc_1371", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -856,34 +1183,46 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 715, - "colNumberStart": 7, - "lineNumberStop": 715, - "colNumberStop": 9, - "offsetStart": 30075, - "offsetEnd": 30077, - "sourceText": "ERR" + "lineNumberStart": 718, + "colNumberStart": 4, + "lineNumberStop": 718, + "colNumberStop": 25, + "offsetStart": 30149, + "offsetEnd": 30170, + "sourceText": "if(ERR) reach_error();" } }, - "content": "(assume (\u003d ERR 0))" + "content": "((assume (\u003d ERR 0)))[choiceType\u003dALTERNATIVE_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 716, + "lineNumberStart": 719, "colNumberStart": 4, - "lineNumberStop": 716, - "colNumberStop": 11, - "offsetStart": 30099, - "offsetEnd": 30106, - "sourceText": "return 0" + "lineNumberStop": 719, + "colNumberStop": 12, + "offsetStart": 30176, + "offsetEnd": 30184, + "sourceText": "return 0;" } }, "content": "(assign main_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 718, + "colNumberStart": 4, + "lineNumberStop": 719, + "colNumberStop": 25, + "offsetStart": 30149, + "offsetEnd": 30184, + "sourceText": "if(ERR) reach_error();if(ERR) reach_error();return 0;return 0;return 0;return 0;" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/19dportest.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/19dportest.c.json index a433145440..e9a678d6c3 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/19dportest.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/19dportest.c.json @@ -28,27 +28,53 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_1400 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "reach_error_init", - "target": "__loc_1400", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 687, + "colNumberStart": 0, + "lineNumberStop": 687, + "colNumberStop": 19, + "offsetStart": 29546, + "offsetEnd": 29565, + "sourceText": "void reach_error(){}" + } } }, { - "source": "__loc_1400", + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 687, + "colNumberStart": 0, + "lineNumberStop": 687, + "colNumberStop": 19, + "offsetStart": 29546, + "offsetEnd": 29565, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -57,6 +83,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 687, + "colNumberStart": 0, + "lineNumberStop": 687, + "colNumberStop": 19, + "offsetStart": 29546, + "offsetEnd": 29565, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } } } ] @@ -92,86 +130,79 @@ } ], "vars": [ + { + "name": "thr1_ret", + "type": "Int" + }, + { + "name": "thr1::_", + "type": "Int" + }, { "name": "thr1::i", "type": "Int" } ], "locs": [ - "thr1_init {init}", - "thr1_final {final}", - "__loc_1407 ", - "__loc_1412 ", - "__loc_1418 ", - "__loc_1424 ", - "__loc_1430 ", - "__loc_1436 ", - "__loc_1442 ", - "__loc_1448 ", - "__loc_1454 ", - "__loc_1460 ", - "__loc_1466 ", - "__loc_1472 ", - "__loc_1478 ", - "__loc_1484 ", - "__loc_1490 ", - "__loc_1496 ", - "__loc_1502 ", - "__loc_1508 ", - "__loc_1514 ", - "__loc_1520 ", - "__loc_1526 ", - "__loc_1532 ", - "__loc_1538 ", - "__loc_1544 ", - "__loc_1550 ", - "__loc_1556 ", - "__loc_1562 ", - "__loc_1568 ", - "__loc_1574 ", - "__loc_1580 ", - "__loc_1586 ", - "__loc_1592 ", - "__loc_1598 ", - "__loc_1604 ", - "__loc_1610 ", - "__loc_1616 ", - "__loc_1622 ", - "__loc_1628 ", - "__loc_1634 ", - "__loc_1640 ", - "__loc_1646 ", - "__loc_1655 ", - "__loc_1656 " - ], - "edges": [ { - "source": "__loc_1656", - "target": "thr1_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "thr1_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 691, + "colNumberStart": 0, + "lineNumberStop": 734, + "colNumberStop": 0, + "offsetStart": 29580, + "offsetEnd": 29989, + "sourceText": "void *thr1(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}" + } } }, { - "source": "thr1_init", - "target": "__loc_1407", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "thr1_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 691, + "colNumberStart": 0, + "lineNumberStop": 734, + "colNumberStop": 0, + "offsetStart": 29580, + "offsetEnd": 29989, + "sourceText": "void *thr1(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}" + } } }, { - "source": "__loc_1407", - "target": "__loc_1412", + "name": "__loc_1640", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 733, + "colNumberStart": 4, + "lineNumberStop": 733, + "colNumberStop": 10, + "offsetStart": 29981, + "offsetEnd": 29987, + "sourceText": "x +\u003d i;" + } + } + } + ], + "edges": [ + { + "source": "thr1_init", + "target": "__loc_1640", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -194,20 +225,7 @@ } }, "content": "(assign thr1::i 0)" - } - ] - } - }, - { - "source": "__loc_1412", - "target": "__loc_1418", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -216,27 +234,14 @@ "lineNumberStart": 693, "colNumberStart": 4, "lineNumberStop": 693, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29621, - "offsetEnd": 29623, - "sourceText": "i++" + "offsetEnd": 29624, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1418", - "target": "__loc_1424", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 1)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -245,27 +250,14 @@ "lineNumberStart": 694, "colNumberStart": 4, "lineNumberStop": 694, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29630, - "offsetEnd": 29632, - "sourceText": "i++" + "offsetEnd": 29633, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1424", - "target": "__loc_1430", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 2)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -274,27 +266,14 @@ "lineNumberStart": 695, "colNumberStart": 4, "lineNumberStop": 695, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29639, - "offsetEnd": 29641, - "sourceText": "i++" + "offsetEnd": 29642, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1430", - "target": "__loc_1436", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 3)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -303,27 +282,14 @@ "lineNumberStart": 696, "colNumberStart": 4, "lineNumberStop": 696, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29648, - "offsetEnd": 29650, - "sourceText": "i++" + "offsetEnd": 29651, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1436", - "target": "__loc_1442", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 4)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -332,27 +298,14 @@ "lineNumberStart": 697, "colNumberStart": 4, "lineNumberStop": 697, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29657, - "offsetEnd": 29659, - "sourceText": "i++" + "offsetEnd": 29660, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1442", - "target": "__loc_1448", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 5)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -361,27 +314,14 @@ "lineNumberStart": 698, "colNumberStart": 4, "lineNumberStop": 698, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29666, - "offsetEnd": 29668, - "sourceText": "i++" + "offsetEnd": 29669, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1448", - "target": "__loc_1454", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 6)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -390,27 +330,14 @@ "lineNumberStart": 699, "colNumberStart": 4, "lineNumberStop": 699, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29675, - "offsetEnd": 29677, - "sourceText": "i++" + "offsetEnd": 29678, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1454", - "target": "__loc_1460", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 7)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -419,27 +346,14 @@ "lineNumberStart": 700, "colNumberStart": 4, "lineNumberStop": 700, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29684, - "offsetEnd": 29686, - "sourceText": "i++" + "offsetEnd": 29687, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1460", - "target": "__loc_1466", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 8)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -448,27 +362,14 @@ "lineNumberStart": 701, "colNumberStart": 4, "lineNumberStop": 701, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29693, - "offsetEnd": 29695, - "sourceText": "i++" + "offsetEnd": 29696, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1466", - "target": "__loc_1472", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 9)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -477,27 +378,14 @@ "lineNumberStart": 702, "colNumberStart": 4, "lineNumberStop": 702, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29702, - "offsetEnd": 29704, - "sourceText": "i++" + "offsetEnd": 29705, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1472", - "target": "__loc_1478", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 10)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -506,27 +394,14 @@ "lineNumberStart": 703, "colNumberStart": 4, "lineNumberStop": 703, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29711, - "offsetEnd": 29713, - "sourceText": "i++" + "offsetEnd": 29714, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1478", - "target": "__loc_1484", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 11)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -535,27 +410,14 @@ "lineNumberStart": 704, "colNumberStart": 4, "lineNumberStop": 704, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29720, - "offsetEnd": 29722, - "sourceText": "i++" + "offsetEnd": 29723, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1484", - "target": "__loc_1490", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 12)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -564,27 +426,14 @@ "lineNumberStart": 705, "colNumberStart": 4, "lineNumberStop": 705, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29729, - "offsetEnd": 29731, - "sourceText": "i++" + "offsetEnd": 29732, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1490", - "target": "__loc_1496", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 13)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -593,27 +442,14 @@ "lineNumberStart": 706, "colNumberStart": 4, "lineNumberStop": 706, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29738, - "offsetEnd": 29740, - "sourceText": "i++" + "offsetEnd": 29741, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1496", - "target": "__loc_1502", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 14)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -622,27 +458,14 @@ "lineNumberStart": 707, "colNumberStart": 4, "lineNumberStop": 707, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29747, - "offsetEnd": 29749, - "sourceText": "i++" + "offsetEnd": 29750, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1502", - "target": "__loc_1508", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 15)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -651,27 +474,14 @@ "lineNumberStart": 708, "colNumberStart": 4, "lineNumberStop": 708, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29756, - "offsetEnd": 29758, - "sourceText": "i++" + "offsetEnd": 29759, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1508", - "target": "__loc_1514", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 16)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -680,27 +490,14 @@ "lineNumberStart": 709, "colNumberStart": 4, "lineNumberStop": 709, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29765, - "offsetEnd": 29767, - "sourceText": "i++" + "offsetEnd": 29768, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1514", - "target": "__loc_1520", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 17)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -709,27 +506,14 @@ "lineNumberStart": 710, "colNumberStart": 4, "lineNumberStop": 710, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29774, - "offsetEnd": 29776, - "sourceText": "i++" + "offsetEnd": 29777, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1520", - "target": "__loc_1526", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 18)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -738,27 +522,14 @@ "lineNumberStart": 711, "colNumberStart": 4, "lineNumberStop": 711, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29783, - "offsetEnd": 29785, - "sourceText": "i++" + "offsetEnd": 29786, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1526", - "target": "__loc_1532", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 19)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -767,27 +538,14 @@ "lineNumberStart": 712, "colNumberStart": 4, "lineNumberStop": 712, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29792, - "offsetEnd": 29794, - "sourceText": "i++" + "offsetEnd": 29795, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1532", - "target": "__loc_1538", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 20)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -796,27 +554,14 @@ "lineNumberStart": 713, "colNumberStart": 4, "lineNumberStop": 713, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29801, - "offsetEnd": 29803, - "sourceText": "i++" + "offsetEnd": 29804, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1538", - "target": "__loc_1544", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 21)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -825,27 +570,14 @@ "lineNumberStart": 714, "colNumberStart": 4, "lineNumberStop": 714, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29810, - "offsetEnd": 29812, - "sourceText": "i++" + "offsetEnd": 29813, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1544", - "target": "__loc_1550", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 22)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -854,27 +586,14 @@ "lineNumberStart": 715, "colNumberStart": 4, "lineNumberStop": 715, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29819, - "offsetEnd": 29821, - "sourceText": "i++" + "offsetEnd": 29822, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1550", - "target": "__loc_1556", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 23)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -883,27 +602,14 @@ "lineNumberStart": 716, "colNumberStart": 4, "lineNumberStop": 716, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29828, - "offsetEnd": 29830, - "sourceText": "i++" + "offsetEnd": 29831, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1556", - "target": "__loc_1562", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 24)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -912,27 +618,14 @@ "lineNumberStart": 717, "colNumberStart": 4, "lineNumberStop": 717, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29837, - "offsetEnd": 29839, - "sourceText": "i++" + "offsetEnd": 29840, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1562", - "target": "__loc_1568", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 25)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -941,27 +634,14 @@ "lineNumberStart": 718, "colNumberStart": 4, "lineNumberStop": 718, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29846, - "offsetEnd": 29848, - "sourceText": "i++" + "offsetEnd": 29849, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1568", - "target": "__loc_1574", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 26)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -970,27 +650,14 @@ "lineNumberStart": 719, "colNumberStart": 4, "lineNumberStop": 719, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29855, - "offsetEnd": 29857, - "sourceText": "i++" + "offsetEnd": 29858, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1574", - "target": "__loc_1580", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 27)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -999,27 +666,14 @@ "lineNumberStart": 720, "colNumberStart": 4, "lineNumberStop": 720, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29864, - "offsetEnd": 29866, - "sourceText": "i++" + "offsetEnd": 29867, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1580", - "target": "__loc_1586", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 28)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1028,27 +682,14 @@ "lineNumberStart": 721, "colNumberStart": 4, "lineNumberStop": 721, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29873, - "offsetEnd": 29875, - "sourceText": "i++" + "offsetEnd": 29876, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1586", - "target": "__loc_1592", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 29)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1057,27 +698,14 @@ "lineNumberStart": 722, "colNumberStart": 4, "lineNumberStop": 722, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29882, - "offsetEnd": 29884, - "sourceText": "i++" + "offsetEnd": 29885, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1592", - "target": "__loc_1598", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 30)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1086,27 +714,14 @@ "lineNumberStart": 723, "colNumberStart": 4, "lineNumberStop": 723, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29891, - "offsetEnd": 29893, - "sourceText": "i++" + "offsetEnd": 29894, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1598", - "target": "__loc_1604", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 31)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1115,27 +730,14 @@ "lineNumberStart": 724, "colNumberStart": 4, "lineNumberStop": 724, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29900, - "offsetEnd": 29902, - "sourceText": "i++" + "offsetEnd": 29903, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1604", - "target": "__loc_1610", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 32)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1144,27 +746,14 @@ "lineNumberStart": 725, "colNumberStart": 4, "lineNumberStop": 725, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29909, - "offsetEnd": 29911, - "sourceText": "i++" + "offsetEnd": 29912, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1610", - "target": "__loc_1616", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 33)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1173,27 +762,14 @@ "lineNumberStart": 726, "colNumberStart": 4, "lineNumberStop": 726, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29918, - "offsetEnd": 29920, - "sourceText": "i++" + "offsetEnd": 29921, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1616", - "target": "__loc_1622", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 34)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1202,27 +778,14 @@ "lineNumberStart": 727, "colNumberStart": 4, "lineNumberStop": 727, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29927, - "offsetEnd": 29929, - "sourceText": "i++" + "offsetEnd": 29930, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1622", - "target": "__loc_1628", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 35)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1231,27 +794,14 @@ "lineNumberStart": 728, "colNumberStart": 4, "lineNumberStop": 728, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29936, - "offsetEnd": 29938, - "sourceText": "i++" + "offsetEnd": 29939, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1628", - "target": "__loc_1634", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 36)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1260,27 +810,14 @@ "lineNumberStart": 729, "colNumberStart": 4, "lineNumberStop": 729, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29945, - "offsetEnd": 29947, - "sourceText": "i++" + "offsetEnd": 29948, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1634", - "target": "__loc_1640", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 37)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1289,27 +826,14 @@ "lineNumberStart": 730, "colNumberStart": 4, "lineNumberStop": 730, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29954, - "offsetEnd": 29956, - "sourceText": "i++" + "offsetEnd": 29957, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1640", - "target": "__loc_1646", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 38)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1318,27 +842,14 @@ "lineNumberStart": 731, "colNumberStart": 4, "lineNumberStop": 731, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29963, - "offsetEnd": 29965, - "sourceText": "i++" + "offsetEnd": 29966, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" - } - ] - } - }, - { - "source": "__loc_1646", - "target": "__loc_1655", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr1::i 39)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1347,20 +858,32 @@ "lineNumberStart": 732, "colNumberStart": 4, "lineNumberStop": 732, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 29972, - "offsetEnd": 29974, - "sourceText": "i++" + "offsetEnd": 29975, + "sourceText": "i++;" } }, - "content": "(assign thr1::i (+ thr1::i 1))" + "content": "(assign thr1::i 40)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 691, + "colNumberStart": 0, + "lineNumberStop": 734, + "colNumberStop": 13, + "offsetStart": 29580, + "offsetEnd": 29989, + "sourceText": "void *thr1(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;int i \u003d 0;int i \u003d 0;int i \u003d 0;int i \u003d 0;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;x +\u003d i;x +\u003d i;x +\u003d i;" + } } }, { - "source": "__loc_1655", - "target": "__loc_1656", + "source": "__loc_1640", + "target": "thr1_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1373,18 +896,24 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign x (+ x thr1::i))" + "content": "(assign x (+ x 40))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 734, + "colNumberStop": 0, + "offsetStart": 0, + "offsetEnd": 29989, + "sourceText": "void *thr1(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}" + } } } ] @@ -1420,86 +949,79 @@ } ], "vars": [ + { + "name": "thr2_ret", + "type": "Int" + }, + { + "name": "thr2::_", + "type": "Int" + }, { "name": "thr2::i", "type": "Int" } ], "locs": [ - "thr2_init {init}", - "thr2_final {final}", - "__loc_1663 ", - "__loc_1668 ", - "__loc_1674 ", - "__loc_1680 ", - "__loc_1686 ", - "__loc_1692 ", - "__loc_1698 ", - "__loc_1704 ", - "__loc_1710 ", - "__loc_1716 ", - "__loc_1722 ", - "__loc_1728 ", - "__loc_1734 ", - "__loc_1740 ", - "__loc_1746 ", - "__loc_1752 ", - "__loc_1758 ", - "__loc_1764 ", - "__loc_1770 ", - "__loc_1776 ", - "__loc_1782 ", - "__loc_1788 ", - "__loc_1794 ", - "__loc_1800 ", - "__loc_1806 ", - "__loc_1812 ", - "__loc_1818 ", - "__loc_1824 ", - "__loc_1830 ", - "__loc_1836 ", - "__loc_1842 ", - "__loc_1848 ", - "__loc_1854 ", - "__loc_1860 ", - "__loc_1866 ", - "__loc_1872 ", - "__loc_1878 ", - "__loc_1884 ", - "__loc_1890 ", - "__loc_1896 ", - "__loc_1902 ", - "__loc_1911 ", - "__loc_1912 " - ], - "edges": [ { - "source": "__loc_1912", - "target": "thr2_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "thr2_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 736, + "colNumberStart": 0, + "lineNumberStop": 779, + "colNumberStop": 0, + "offsetStart": 29992, + "offsetEnd": 30401, + "sourceText": "void *thr2(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}" + } } }, { - "source": "thr2_init", - "target": "__loc_1663", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "thr2_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 736, + "colNumberStart": 0, + "lineNumberStop": 779, + "colNumberStop": 0, + "offsetStart": 29992, + "offsetEnd": 30401, + "sourceText": "void *thr2(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}" + } } }, { - "source": "__loc_1663", - "target": "__loc_1668", + "name": "__loc_1895", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 778, + "colNumberStart": 4, + "lineNumberStop": 778, + "colNumberStop": 10, + "offsetStart": 30393, + "offsetEnd": 30399, + "sourceText": "x +\u003d i;" + } + } + } + ], + "edges": [ + { + "source": "thr2_init", + "target": "__loc_1895", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1522,20 +1044,7 @@ } }, "content": "(assign thr2::i 0)" - } - ] - } - }, - { - "source": "__loc_1668", - "target": "__loc_1674", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1544,27 +1053,14 @@ "lineNumberStart": 738, "colNumberStart": 4, "lineNumberStop": 738, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30033, - "offsetEnd": 30035, - "sourceText": "i++" + "offsetEnd": 30036, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1674", - "target": "__loc_1680", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 1)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1573,27 +1069,14 @@ "lineNumberStart": 739, "colNumberStart": 4, "lineNumberStop": 739, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30042, - "offsetEnd": 30044, - "sourceText": "i++" + "offsetEnd": 30045, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1680", - "target": "__loc_1686", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 2)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1602,27 +1085,14 @@ "lineNumberStart": 740, "colNumberStart": 4, "lineNumberStop": 740, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30051, - "offsetEnd": 30053, - "sourceText": "i++" + "offsetEnd": 30054, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1686", - "target": "__loc_1692", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 3)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1631,27 +1101,14 @@ "lineNumberStart": 741, "colNumberStart": 4, "lineNumberStop": 741, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30060, - "offsetEnd": 30062, - "sourceText": "i++" + "offsetEnd": 30063, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1692", - "target": "__loc_1698", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 4)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1660,27 +1117,14 @@ "lineNumberStart": 742, "colNumberStart": 4, "lineNumberStop": 742, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30069, - "offsetEnd": 30071, - "sourceText": "i++" + "offsetEnd": 30072, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1698", - "target": "__loc_1704", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 5)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1689,27 +1133,14 @@ "lineNumberStart": 743, "colNumberStart": 4, "lineNumberStop": 743, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30078, - "offsetEnd": 30080, - "sourceText": "i++" + "offsetEnd": 30081, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1704", - "target": "__loc_1710", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 6)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1718,27 +1149,14 @@ "lineNumberStart": 744, "colNumberStart": 4, "lineNumberStop": 744, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30087, - "offsetEnd": 30089, - "sourceText": "i++" + "offsetEnd": 30090, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1710", - "target": "__loc_1716", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 7)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1747,27 +1165,14 @@ "lineNumberStart": 745, "colNumberStart": 4, "lineNumberStop": 745, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30096, - "offsetEnd": 30098, - "sourceText": "i++" + "offsetEnd": 30099, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1716", - "target": "__loc_1722", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 8)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1776,27 +1181,14 @@ "lineNumberStart": 746, "colNumberStart": 4, "lineNumberStop": 746, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30105, - "offsetEnd": 30107, - "sourceText": "i++" + "offsetEnd": 30108, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1722", - "target": "__loc_1728", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 9)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1805,27 +1197,14 @@ "lineNumberStart": 747, "colNumberStart": 4, "lineNumberStop": 747, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30114, - "offsetEnd": 30116, - "sourceText": "i++" + "offsetEnd": 30117, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1728", - "target": "__loc_1734", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 10)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1834,27 +1213,14 @@ "lineNumberStart": 748, "colNumberStart": 4, "lineNumberStop": 748, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30123, - "offsetEnd": 30125, - "sourceText": "i++" + "offsetEnd": 30126, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1734", - "target": "__loc_1740", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 11)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1863,27 +1229,14 @@ "lineNumberStart": 749, "colNumberStart": 4, "lineNumberStop": 749, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30132, - "offsetEnd": 30134, - "sourceText": "i++" + "offsetEnd": 30135, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1740", - "target": "__loc_1746", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 12)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1892,27 +1245,14 @@ "lineNumberStart": 750, "colNumberStart": 4, "lineNumberStop": 750, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30141, - "offsetEnd": 30143, - "sourceText": "i++" + "offsetEnd": 30144, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1746", - "target": "__loc_1752", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 13)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1921,27 +1261,14 @@ "lineNumberStart": 751, "colNumberStart": 4, "lineNumberStop": 751, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30150, - "offsetEnd": 30152, - "sourceText": "i++" + "offsetEnd": 30153, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1752", - "target": "__loc_1758", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 14)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1950,27 +1277,14 @@ "lineNumberStart": 752, "colNumberStart": 4, "lineNumberStop": 752, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30159, - "offsetEnd": 30161, - "sourceText": "i++" + "offsetEnd": 30162, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1758", - "target": "__loc_1764", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 15)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -1979,27 +1293,14 @@ "lineNumberStart": 753, "colNumberStart": 4, "lineNumberStop": 753, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30168, - "offsetEnd": 30170, - "sourceText": "i++" + "offsetEnd": 30171, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1764", - "target": "__loc_1770", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 16)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2008,27 +1309,14 @@ "lineNumberStart": 754, "colNumberStart": 4, "lineNumberStop": 754, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30177, - "offsetEnd": 30179, - "sourceText": "i++" + "offsetEnd": 30180, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1770", - "target": "__loc_1776", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 17)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2037,27 +1325,14 @@ "lineNumberStart": 755, "colNumberStart": 4, "lineNumberStop": 755, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30186, - "offsetEnd": 30188, - "sourceText": "i++" + "offsetEnd": 30189, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1776", - "target": "__loc_1782", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 18)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2066,27 +1341,14 @@ "lineNumberStart": 756, "colNumberStart": 4, "lineNumberStop": 756, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30195, - "offsetEnd": 30197, - "sourceText": "i++" + "offsetEnd": 30198, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1782", - "target": "__loc_1788", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 19)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2095,27 +1357,14 @@ "lineNumberStart": 757, "colNumberStart": 4, "lineNumberStop": 757, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30204, - "offsetEnd": 30206, - "sourceText": "i++" + "offsetEnd": 30207, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1788", - "target": "__loc_1794", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 20)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2124,27 +1373,14 @@ "lineNumberStart": 758, "colNumberStart": 4, "lineNumberStop": 758, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30213, - "offsetEnd": 30215, - "sourceText": "i++" + "offsetEnd": 30216, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1794", - "target": "__loc_1800", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 21)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2153,27 +1389,14 @@ "lineNumberStart": 759, "colNumberStart": 4, "lineNumberStop": 759, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30222, - "offsetEnd": 30224, - "sourceText": "i++" + "offsetEnd": 30225, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1800", - "target": "__loc_1806", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 22)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2182,27 +1405,14 @@ "lineNumberStart": 760, "colNumberStart": 4, "lineNumberStop": 760, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30231, - "offsetEnd": 30233, - "sourceText": "i++" + "offsetEnd": 30234, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1806", - "target": "__loc_1812", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 23)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2211,27 +1421,14 @@ "lineNumberStart": 761, "colNumberStart": 4, "lineNumberStop": 761, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30240, - "offsetEnd": 30242, - "sourceText": "i++" + "offsetEnd": 30243, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1812", - "target": "__loc_1818", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 24)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2240,27 +1437,14 @@ "lineNumberStart": 762, "colNumberStart": 4, "lineNumberStop": 762, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30249, - "offsetEnd": 30251, - "sourceText": "i++" + "offsetEnd": 30252, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1818", - "target": "__loc_1824", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 25)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2269,27 +1453,14 @@ "lineNumberStart": 763, "colNumberStart": 4, "lineNumberStop": 763, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30258, - "offsetEnd": 30260, - "sourceText": "i++" + "offsetEnd": 30261, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1824", - "target": "__loc_1830", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 26)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2298,27 +1469,14 @@ "lineNumberStart": 764, "colNumberStart": 4, "lineNumberStop": 764, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30267, - "offsetEnd": 30269, - "sourceText": "i++" + "offsetEnd": 30270, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1830", - "target": "__loc_1836", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 27)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2327,27 +1485,14 @@ "lineNumberStart": 765, "colNumberStart": 4, "lineNumberStop": 765, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30276, - "offsetEnd": 30278, - "sourceText": "i++" + "offsetEnd": 30279, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1836", - "target": "__loc_1842", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 28)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2356,27 +1501,14 @@ "lineNumberStart": 766, "colNumberStart": 4, "lineNumberStop": 766, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30285, - "offsetEnd": 30287, - "sourceText": "i++" + "offsetEnd": 30288, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1842", - "target": "__loc_1848", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 29)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2384,28 +1516,15 @@ "content": { "lineNumberStart": 767, "colNumberStart": 4, - "lineNumberStop": 767, - "colNumberStop": 6, - "offsetStart": 30294, - "offsetEnd": 30296, - "sourceText": "i++" - } - }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1848", - "target": "__loc_1854", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "lineNumberStop": 767, + "colNumberStop": 7, + "offsetStart": 30294, + "offsetEnd": 30297, + "sourceText": "i++;" + } + }, + "content": "(assign thr2::i 30)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2414,27 +1533,14 @@ "lineNumberStart": 768, "colNumberStart": 4, "lineNumberStop": 768, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30303, - "offsetEnd": 30305, - "sourceText": "i++" + "offsetEnd": 30306, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1854", - "target": "__loc_1860", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 31)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2443,27 +1549,14 @@ "lineNumberStart": 769, "colNumberStart": 4, "lineNumberStop": 769, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30312, - "offsetEnd": 30314, - "sourceText": "i++" + "offsetEnd": 30315, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1860", - "target": "__loc_1866", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 32)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2472,27 +1565,14 @@ "lineNumberStart": 770, "colNumberStart": 4, "lineNumberStop": 770, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30321, - "offsetEnd": 30323, - "sourceText": "i++" + "offsetEnd": 30324, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1866", - "target": "__loc_1872", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 33)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2501,27 +1581,14 @@ "lineNumberStart": 771, "colNumberStart": 4, "lineNumberStop": 771, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30330, - "offsetEnd": 30332, - "sourceText": "i++" + "offsetEnd": 30333, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1872", - "target": "__loc_1878", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 34)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2530,27 +1597,14 @@ "lineNumberStart": 772, "colNumberStart": 4, "lineNumberStop": 772, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30339, - "offsetEnd": 30341, - "sourceText": "i++" + "offsetEnd": 30342, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1878", - "target": "__loc_1884", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 35)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2559,27 +1613,14 @@ "lineNumberStart": 773, "colNumberStart": 4, "lineNumberStop": 773, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30348, - "offsetEnd": 30350, - "sourceText": "i++" + "offsetEnd": 30351, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1884", - "target": "__loc_1890", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 36)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2588,27 +1629,14 @@ "lineNumberStart": 774, "colNumberStart": 4, "lineNumberStop": 774, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30357, - "offsetEnd": 30359, - "sourceText": "i++" + "offsetEnd": 30360, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1890", - "target": "__loc_1896", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 37)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2617,27 +1645,14 @@ "lineNumberStart": 775, "colNumberStart": 4, "lineNumberStop": 775, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30366, - "offsetEnd": 30368, - "sourceText": "i++" + "offsetEnd": 30369, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1896", - "target": "__loc_1902", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 38)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2646,27 +1661,14 @@ "lineNumberStart": 776, "colNumberStart": 4, "lineNumberStop": 776, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30375, - "offsetEnd": 30377, - "sourceText": "i++" + "offsetEnd": 30378, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" - } - ] - } - }, - { - "source": "__loc_1902", - "target": "__loc_1911", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign thr2::i 39)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2675,20 +1677,32 @@ "lineNumberStart": 777, "colNumberStart": 4, "lineNumberStop": 777, - "colNumberStop": 6, + "colNumberStop": 7, "offsetStart": 30384, - "offsetEnd": 30386, - "sourceText": "i++" + "offsetEnd": 30387, + "sourceText": "i++;" } }, - "content": "(assign thr2::i (+ thr2::i 1))" + "content": "(assign thr2::i 40)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 736, + "colNumberStart": 0, + "lineNumberStop": 779, + "colNumberStop": 13, + "offsetStart": 29992, + "offsetEnd": 30401, + "sourceText": "void *thr2(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;int i \u003d 0;int i \u003d 0;int i \u003d 0;int i \u003d 0;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;i++;x +\u003d i;x +\u003d i;x +\u003d i;" + } } }, { - "source": "__loc_1911", - "target": "__loc_1912", + "source": "__loc_1895", + "target": "thr2_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2701,18 +1715,24 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign x (+ x thr2::i))" + "content": "(assign x (+ x 40))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 779, + "colNumberStop": 0, + "offsetStart": 0, + "offsetEnd": 30401, + "sourceText": "void *thr2(void *_) {\n int i \u003d 0;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n i++;\n x +\u003d i;\n}" + } } } ] @@ -2735,6 +1755,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::t1", "type": "Int" @@ -2744,24 +1768,138 @@ "type": "Int" }, { - "name": "main_ret", + "name": "call_pthread_create_ret88", + "type": "Int" + }, + { + "name": "call_pthread_create_ret89", + "type": "Int" + }, + { + "name": "call_reach_error_ret90", + "type": "Int" + }, + { + "name": "call_pthread_join_ret91", + "type": "Int" + }, + { + "name": "call_pthread_join_ret92", "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_1936 ", - "__loc_1954 ", - "__loc_1962 ", - "__loc_1980 ", - "__loc_1992 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 781, + "colNumberStart": 0, + "lineNumberStop": 792, + "colNumberStop": 0, + "offsetStart": 30404, + "offsetEnd": 30644, + "sourceText": "int main() {\n// for(int i \u003d 0; i \u003c 16; ++i) {\n pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(x \u003e 41) reach_error();\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n// }\n\n return 0;\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 781, + "colNumberStart": 0, + "lineNumberStop": 792, + "colNumberStop": 0, + "offsetStart": 30404, + "offsetEnd": 30644, + "sourceText": "int main() {\n// for(int i \u003d 0; i \u003c 16; ++i) {\n pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(x \u003e 41) reach_error();\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n// }\n\n return 0;\n}" + } + } + }, + { + "name": "__loc_1920", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1938", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1946", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1964", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_1976", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_1962", - "target": "__loc_1980", + "source": "main_init", + "target": "__loc_1920", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2769,28 +1907,52 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "content": "(assign x 0)" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 786, - "colNumberStart": 5, - "lineNumberStop": 786, - "colNumberStop": 10, - "offsetStart": 30552, - "offsetEnd": 30557, - "sourceText": "x \u003e 41" + "sourceText": "" + } + }, + "content": "((assume (and (\u003e\u003d main::t1 0) (\u003c\u003d main::t1 18446744073709551615))))[choiceType\u003dMAIN_PATH]" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" } }, - "content": "(assume (\u003d (ite (\u003e x 41) 1 0) 0))" + "content": "((assume (and (\u003e\u003d main::t2 0) (\u003c\u003d main::t2 18446744073709551615))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 781, + "colNumberStart": 0, + "lineNumberStop": 792, + "colNumberStop": 35, + "offsetStart": 30404, + "offsetEnd": 30644, + "sourceText": "int main() {\n// for(int i \u003d 0; i \u003c 16; ++i) {\n pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(x \u003e 41) reach_error();\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n// }\n\n return 0;\n}pthread_t t1, t2;\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n if(x \u003e 41) reach_error();\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n// }\n\n return 0;pthread_t t1, t2;pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);" + } } }, { - "source": "__loc_1936", - "target": "__loc_1954", + "source": "__loc_1920", + "target": "__loc_1938", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2806,20 +1968,32 @@ "lineNumberStart": 784, "colNumberStart": 4, "lineNumberStop": 784, - "colNumberStop": 34, + "colNumberStop": 35, "offsetStart": 30477, - "offsetEnd": 30507, - "sourceText": "pthread_create(\u0026t1, 0, thr1, 0)" + "offsetEnd": 30508, + "sourceText": "pthread_create(\u0026t1, 0, thr1, 0);" } }, - "content": "(var main::t1 Int) \u003d start thr1(0)" + "content": "(var main::t1 Int) \u003d start thr1(0, 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 784, + "colNumberStart": 4, + "lineNumberStop": 785, + "colNumberStop": 35, + "offsetStart": 30477, + "offsetEnd": 30545, + "sourceText": "pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);" + } } }, { - "source": "__loc_1954", - "target": "__loc_1962", + "source": "__loc_1938", + "target": "__loc_1946", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2835,20 +2009,32 @@ "lineNumberStart": 785, "colNumberStart": 4, "lineNumberStop": 785, - "colNumberStop": 34, + "colNumberStop": 35, "offsetStart": 30514, - "offsetEnd": 30544, - "sourceText": "pthread_create(\u0026t2, 0, thr2, 0)" + "offsetEnd": 30545, + "sourceText": "pthread_create(\u0026t2, 0, thr2, 0);" } }, - "content": "(var main::t2 Int) \u003d start thr2(0)" + "content": "(var main::t2 Int) \u003d start thr2(0, 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 785, + "colNumberStart": 2, + "lineNumberStop": 786, + "colNumberStop": 35, + "offsetStart": 30514, + "offsetEnd": 30573, + "sourceText": "pthread_create(\u0026t2, 0, thr2, 0);if(x \u003e 41) reach_error();if(x \u003e 41) reach_error();if(x \u003e 41) reach_error();" + } } }, { - "source": "__loc_1980", - "target": "__loc_1992", + "source": "__loc_1946", + "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2857,27 +2043,39 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.JoinLabel", + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 787, - "colNumberStart": 4, - "lineNumberStop": 787, - "colNumberStop": 22, - "offsetStart": 30579, - "offsetEnd": 30597, - "sourceText": "pthread_join(t1, 0)" + "lineNumberStart": 786, + "colNumberStart": 2, + "lineNumberStop": 786, + "colNumberStop": 26, + "offsetStart": 30549, + "offsetEnd": 30573, + "sourceText": "if(x \u003e 41) reach_error();" } }, - "content": "join (var main::t1 Int)" + "content": "((assume (/\u003d (ite (\u003e x 41) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 786, + "colNumberStart": 2, + "lineNumberStop": 786, + "colNumberStop": 26, + "offsetStart": 30549, + "offsetEnd": 30573, + "sourceText": "if(x \u003e 41) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { - "source": "main_init", - "target": "__loc_1936", + "source": "__loc_1946", + "target": "__loc_1964", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2885,52 +2083,40 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "content": "(assign x 0)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" - } - }, - "content": "(assume (and (\u003e\u003d main::t1 0) (\u003c\u003d main::t1 4294967295)))" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 786, + "colNumberStart": 2, + "lineNumberStop": 786, + "colNumberStop": 26, + "offsetStart": 30549, + "offsetEnd": 30573, + "sourceText": "if(x \u003e 41) reach_error();" } }, - "content": "(assume (and (\u003e\u003d main::t2 0) (\u003c\u003d main::t2 4294967295)))" + "content": "((assume (\u003d (ite (\u003e x 41) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 786, + "colNumberStart": 2, + "lineNumberStop": 787, + "colNumberStop": 26, + "offsetStart": 30549, + "offsetEnd": 30598, + "sourceText": "if(x \u003e 41) reach_error();if(x \u003e 41) reach_error();pthread_join(t1, 0);pthread_join(t1, 0);pthread_join(t1, 0);pthread_join(t1, 0);pthread_join(t1, 0);" + } } }, { - "source": "__loc_1962", - "target": "main_error", + "source": "__loc_1964", + "target": "__loc_1976", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2939,26 +2125,38 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.JoinLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 786, - "colNumberStart": 5, - "lineNumberStop": 786, - "colNumberStop": 10, - "offsetStart": 30552, - "offsetEnd": 30557, - "sourceText": "x \u003e 41" + "lineNumberStart": 787, + "colNumberStart": 4, + "lineNumberStop": 787, + "colNumberStop": 23, + "offsetStart": 30579, + "offsetEnd": 30598, + "sourceText": "pthread_join(t1, 0);" } }, - "content": "(assume (/\u003d (ite (\u003e x 41) 1 0) 0))" + "content": "join (var main::t1 Int)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 787, + "colNumberStart": 4, + "lineNumberStop": 788, + "colNumberStop": 23, + "offsetStart": 30579, + "offsetEnd": 30623, + "sourceText": "pthread_join(t1, 0);pthread_join(t2, 0);pthread_join(t2, 0);pthread_join(t2, 0);pthread_join(t2, 0);pthread_join(t2, 0);" + } } }, { - "source": "__loc_1992", + "source": "__loc_1976", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -2975,10 +2173,10 @@ "lineNumberStart": 788, "colNumberStart": 4, "lineNumberStop": 788, - "colNumberStop": 22, + "colNumberStop": 23, "offsetStart": 30604, - "offsetEnd": 30622, - "sourceText": "pthread_join(t2, 0)" + "offsetEnd": 30623, + "sourceText": "pthread_join(t2, 0);" } }, "content": "join (var main::t2 Int)" @@ -2991,15 +2189,27 @@ "lineNumberStart": 791, "colNumberStart": 2, "lineNumberStop": 791, - "colNumberStop": 9, + "colNumberStop": 10, "offsetStart": 30634, - "offsetEnd": 30641, - "sourceText": "return 0" + "offsetEnd": 30642, + "sourceText": "return 0;" } }, "content": "(assign main_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 788, + "colNumberStart": 2, + "lineNumberStop": 791, + "colNumberStop": 23, + "offsetStart": 30604, + "offsetEnd": 30642, + "sourceText": "pthread_join(t2, 0);return 0;return 0;return 0;return 0;" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/20testinline.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/20testinline.c.json index e9eb1fb764..9316a977a8 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/20testinline.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/20testinline.c.json @@ -33,6 +33,10 @@ } ], "vars": [ + { + "name": "func_ret", + "type": "Int" + }, { "name": "func::a", "type": "Int" @@ -40,18 +44,76 @@ { "name": "func::x", "type": "Int" + }, + { + "name": "call_reach_error_ret93", + "type": "Int" } ], "locs": [ - "func_init {init}", - "func_final {final}", - "__loc_2010 ", - "func_error {error}" + { + "name": "func_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 102, + "sourceText": "void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}" + } + } + }, + { + "name": "func_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 102, + "sourceText": "void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}" + } + } + }, + { + "name": "__loc_1995", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "func_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { "source": "func_init", - "target": "__loc_2010", + "target": "__loc_1995", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -64,22 +126,28 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d func::x -2147483648) (\u003c\u003d func::x 2147483647)))" + "content": "((assume (and (\u003e\u003d func::x -2147483648) (\u003c\u003d func::x 2147483647))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 38, + "offsetStart": 21, + "offsetEnd": 102, + "sourceText": "void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;int x;if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();" + } } }, { - "source": "__loc_2010", + "source": "__loc_1995", "target": "func_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -94,21 +162,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 5, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 5, - "colNumberStop": 22, - "offsetStart": 58, - "offsetEnd": 73, - "sourceText": "a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2" + "colNumberStop": 38, + "offsetStart": 55, + "offsetEnd": 89, + "sourceText": "if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();" } }, - "content": "(assume (/\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0))" + "content": "((assume (/\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 5, + "colNumberStop": 38, + "offsetStart": 55, + "offsetEnd": 89, + "sourceText": "if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { - "source": "__loc_2010", + "source": "__loc_1995", "target": "func_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -123,33 +203,39 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 5, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 5, - "colNumberStop": 22, - "offsetStart": 58, - "offsetEnd": 73, - "sourceText": "a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2" + "colNumberStop": 38, + "offsetStart": 55, + "offsetEnd": 89, + "sourceText": "if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();" } }, - "content": "(assume (\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0))" + "content": "((assume (\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, "content": "(assign func::x 1)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 38, + "offsetStart": 0, + "offsetEnd": 102, + "sourceText": "if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();x \u003d 1;x \u003d 1;x \u003d 1;void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}" + } } } ] @@ -172,6 +258,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "call_func_ret94", "type": "Int" @@ -180,6 +270,10 @@ "name": "call_func_ret95", "type": "Int" }, + { + "name": "func_ret", + "type": "Int" + }, { "name": "func::a", "type": "Int" @@ -189,21 +283,62 @@ "type": "Int" }, { - "name": "func_ret", + "name": "call_reach_error_ret93", "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_20102048 ", - "main_error {error}", - "__loc_20102052 " + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 0, + "lineNumberStop": 12, + "colNumberStop": 0, + "offsetStart": 105, + "offsetEnd": 144, + "sourceText": "int main() {\n func(0);\n func(1);\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 9, + "colNumberStart": 0, + "lineNumberStop": 12, + "colNumberStop": 0, + "offsetStart": 105, + "offsetEnd": 144, + "sourceText": "int main() {\n func(0);\n func(1);\n}" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { "source": "main_init", - "target": "__loc_20102048", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -219,99 +354,29 @@ "lineNumberStart": 10, "colNumberStart": 4, "lineNumberStop": 10, - "colNumberStop": 10, + "colNumberStop": 11, "offsetStart": 122, - "offsetEnd": 128, - "sourceText": "func(0)" + "offsetEnd": 129, + "sourceText": "func(0);" } }, - "content": "(assign func::a (+ 0))" + "content": "(assign func::a 0)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d func::x -2147483648) (\u003c\u003d func::x 2147483647)))" - } - ] - } - }, - { - "source": "__loc_20102048", - "target": "main_error", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 5, - "colNumberStart": 7, - "lineNumberStop": 5, - "colNumberStop": 22, - "offsetStart": 58, - "offsetEnd": 73, - "sourceText": "a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2" - } - }, - "content": "(assume (/\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_20102048", - "target": "__loc_20102052", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 5, - "colNumberStart": 7, - "lineNumberStop": 5, - "colNumberStop": 22, - "offsetStart": 58, - "offsetEnd": 73, - "sourceText": "a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2" - } - }, - "content": "(assume (\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0))" + "content": "((assume (and (\u003e\u003d func::x -2147483648) (\u003c\u003d func::x 2147483647))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -325,10 +390,10 @@ "lineNumberStart": 10, "colNumberStart": 4, "lineNumberStop": 10, - "colNumberStop": 10, + "colNumberStop": 11, "offsetStart": 122, - "offsetEnd": 128, - "sourceText": "func(0)" + "offsetEnd": 129, + "sourceText": "func(0);" } }, "content": "(assign call_func_ret94 func_ret)" @@ -341,99 +406,19 @@ "lineNumberStart": 11, "colNumberStart": 4, "lineNumberStop": 11, - "colNumberStop": 10, + "colNumberStop": 11, "offsetStart": 135, - "offsetEnd": 141, - "sourceText": "func(1)" + "offsetEnd": 142, + "sourceText": "func(1);" } }, - "content": "(assign func::a (+ 1))" + "content": "(assign func::a 1)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" - } - }, - "content": "(assume (and (\u003e\u003d func::x -2147483648) (\u003c\u003d func::x 2147483647)))" - } - ] - } - }, - { - "source": "__loc_20102052", - "target": "main_error", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 5, - "colNumberStart": 7, - "lineNumberStop": 5, - "colNumberStop": 22, - "offsetStart": 58, - "offsetEnd": 73, - "sourceText": "a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2" - } - }, - "content": "(assume (/\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_20102052", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 5, - "colNumberStart": 7, - "lineNumberStop": 5, - "colNumberStop": 22, - "offsetStart": 58, - "offsetEnd": 73, - "sourceText": "a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2" - } - }, - "content": "(assume (\u003d (ite (and (/\u003d 0 (ite (\u003d func::a 1) 1 0)) (/\u003d 0 (ite (\u003d func::x 2) 1 0))) 1 0) 0))" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -447,15 +432,27 @@ "lineNumberStart": 11, "colNumberStart": 4, "lineNumberStop": 11, - "colNumberStop": 10, + "colNumberStop": 11, "offsetStart": 135, - "offsetEnd": 141, - "sourceText": "func(1)" + "offsetEnd": 142, + "sourceText": "func(1);" } }, "content": "(assign call_func_ret95 func_ret)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 12, + "colNumberStop": 38, + "offsetStart": 21, + "offsetEnd": 144, + "sourceText": "int main() {\n func(0);\n func(1);\n}func(0);\n func(1);func(0);func(0);func(0);func(0);func(0);void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;int x;if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();x \u003d 1;x \u003d 1;x \u003d 1;void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}func(1);func(1);func(1);func(1);func(1);void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;int x;if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();x \u003d 1;x \u003d 1;x \u003d 1;void func(int a) {\n int x;\n if(a \u003d\u003d 1 \u0026\u0026 x \u003d\u003d 2) reach_error();\n x \u003d 1;\n}int main() {\n func(0);\n func(1);\n}" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/21namecollision.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/21namecollision.c.json index 1f49fd762d..c74271df94 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/21namecollision.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/21namecollision.c.json @@ -2,6 +2,94 @@ "name": "", "vars": [], "procedures": [ + { + "name": "reach_error", + "params": [ + { + "first": { + "type": "hu.bme.mit.theta.core.decl.VarDecl", + "value": { + "name": "reach_error_ret", + "type": "Int" + } + }, + "second": { + "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", + "value": "OUT" + } + } + ], + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } + ], + "locs": [ + { + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + }, + { + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", + "target": "reach_error_final", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } + } + } + ] + }, { "name": "f", "params": [ @@ -34,34 +122,55 @@ ], "vars": [ { - "name": "f::x", + "name": "f_ret", "type": "Int" }, { - "name": "f_ret", + "name": "f::x", "type": "Int" } ], "locs": [ - "f_init {init}", - "f_final {final}", - "__loc_2059 " - ], - "edges": [ { - "source": "f_init", - "target": "__loc_2059", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "f_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 54, + "sourceText": "int f(int x) {\n return x - 1;\n}" + } } }, { - "source": "__loc_2059", + "name": "f_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 0, + "offsetStart": 21, + "offsetEnd": 54, + "sourceText": "int f(int x) {\n return x - 1;\n}" + } + } + } + ], + "edges": [ + { + "source": "f_init", "target": "f_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -75,18 +184,30 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 2, + "lineNumberStart": 3, "colNumberStart": 4, - "lineNumberStop": 2, - "colNumberStop": 15, - "offsetStart": 19, - "offsetEnd": 30, - "sourceText": "return x - 1" + "lineNumberStop": 3, + "colNumberStop": 16, + "offsetStart": 40, + "offsetEnd": 52, + "sourceText": "return x - 1;" } }, "content": "(assign f_ret (+ f::x -1))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 16, + "offsetStart": 21, + "offsetEnd": 54, + "sourceText": "int f(int x) {\n return x - 1;\n}return x - 1;return x - 1;return x - 1;return x - 1;return x - 1;" + } } } ] @@ -123,34 +244,55 @@ ], "vars": [ { - "name": "fp::x", + "name": "fp_ret", "type": "Int" }, { - "name": "fp_ret", + "name": "fp::x", "type": "Int" } ], "locs": [ - "fp_init {init}", - "fp_final {final}", - "__loc_2066 " - ], - "edges": [ { - "source": "fp_init", - "target": "__loc_2066", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "fp_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 0, + "offsetStart": 57, + "offsetEnd": 91, + "sourceText": "int fp(int x) {\n return x + 1;\n}" + } } }, { - "source": "__loc_2066", + "name": "fp_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 0, + "offsetStart": 57, + "offsetEnd": 91, + "sourceText": "int fp(int x) {\n return x + 1;\n}" + } + } + } + ], + "edges": [ + { + "source": "fp_init", "target": "fp_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -164,18 +306,30 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, + "lineNumberStart": 7, "colNumberStart": 4, - "lineNumberStop": 6, - "colNumberStop": 15, - "offsetStart": 56, - "offsetEnd": 67, - "sourceText": "return x + 1" + "lineNumberStop": 7, + "colNumberStop": 16, + "offsetStart": 77, + "offsetEnd": 89, + "sourceText": "return x + 1;" } }, "content": "(assign fp_ret (+ fp::x 1))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 0, + "lineNumberStop": 8, + "colNumberStop": 16, + "offsetStart": 57, + "offsetEnd": 91, + "sourceText": "int fp(int x) {\n return x + 1;\n}return x + 1;return x + 1;return x + 1;return x + 1;return x + 1;" + } } } ] @@ -198,6 +352,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::x", "type": "Int" @@ -227,7 +385,7 @@ "type": "Int" }, { - "name": "f::x", + "name": "call_reach_error_ret102", "type": "Int" }, { @@ -235,23 +393,81 @@ "type": "Int" }, { - "name": "fp::x", + "name": "f::x", "type": "Int" }, { "name": "fp_ret", "type": "Int" + }, + { + "name": "fp::x", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_2135 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 0, + "offsetStart": 94, + "offsetEnd": 215, + "sourceText": "int main() {\n int x;\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n if(x \u003d\u003d -2) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 0, + "offsetStart": 94, + "offsetEnd": 215, + "sourceText": "int main() {\n int x;\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n if(x \u003d\u003d -2) reach_error();\n}" + } + } + }, + { + "name": "__loc_2168", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_2135", + "source": "__loc_2168", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -265,22 +481,34 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 14, - "colNumberStart": 7, - "lineNumberStop": 14, - "colNumberStop": 13, - "offsetStart": 170, - "offsetEnd": 176, - "sourceText": "x \u003d\u003d -2" + "lineNumberStart": 15, + "colNumberStart": 4, + "lineNumberStop": 15, + "colNumberStop": 29, + "offsetStart": 188, + "offsetEnd": 213, + "sourceText": "if(x \u003d\u003d -2) reach_error();" } }, - "content": "(assume (\u003d (ite (\u003d main::x -2) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003d main::x -2) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 29, + "offsetStart": 94, + "offsetEnd": 215, + "sourceText": "if(x \u003d\u003d -2) reach_error();if(x \u003d\u003d -2) reach_error();int main() {\n int x;\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n if(x \u003d\u003d -2) reach_error();\n}" + } } }, { - "source": "__loc_2135", + "source": "__loc_2168", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -294,23 +522,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 14, - "colNumberStart": 7, - "lineNumberStop": 14, - "colNumberStop": 13, - "offsetStart": 170, - "offsetEnd": 176, - "sourceText": "x \u003d\u003d -2" + "lineNumberStart": 15, + "colNumberStart": 4, + "lineNumberStop": 15, + "colNumberStop": 29, + "offsetStart": 188, + "offsetEnd": 213, + "sourceText": "if(x \u003d\u003d -2) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003d main::x -2) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003d main::x -2) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 15, + "colNumberStart": 4, + "lineNumberStop": 15, + "colNumberStop": 29, + "offsetStart": 188, + "offsetEnd": 213, + "sourceText": "if(x \u003d\u003d -2) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { "source": "main_init", - "target": "__loc_2135", + "target": "__loc_2168", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -323,45 +563,39 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::x -2147483648) (\u003c\u003d main::x 2147483647)))" + "content": "((assume (and (\u003e\u003d main::x -2147483648) (\u003c\u003d main::x 2147483647))))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 11, - "colNumberStart": 8, - "lineNumberStop": 11, - "colNumberStop": 11, - "offsetStart": 105, - "offsetEnd": 108, - "sourceText": "f(x)" + "lineNumberStart": 12, + "colNumberStart": 4, + "lineNumberStop": 12, + "colNumberStop": 20, + "offsetStart": 122, + "offsetEnd": 138, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign f::x (+ main::x))" + "content": "(assign f::x main::x)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 2, + "lineNumberStart": 3, "colNumberStart": 4, - "lineNumberStop": 2, - "colNumberStop": 15, - "offsetStart": 19, - "offsetEnd": 30, - "sourceText": "return x - 1" + "lineNumberStop": 3, + "colNumberStop": 16, + "offsetStart": 40, + "offsetEnd": 52, + "sourceText": "return x - 1;" } }, "content": "(assign f_ret (+ f::x -1))" @@ -371,45 +605,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 11, - "colNumberStart": 8, - "lineNumberStop": 11, - "colNumberStop": 11, - "offsetStart": 105, - "offsetEnd": 108, - "sourceText": "f(x)" + "lineNumberStart": 12, + "colNumberStart": 4, + "lineNumberStop": 12, + "colNumberStop": 20, + "offsetStart": 122, + "offsetEnd": 138, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign call_f_ret96 (+ f_ret))" + "content": "(assign call_f_ret96 f_ret)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 11, - "colNumberStart": 15, - "lineNumberStop": 11, - "colNumberStop": 19, - "offsetStart": 112, - "offsetEnd": 116, - "sourceText": "fp(x)" + "lineNumberStart": 12, + "colNumberStart": 4, + "lineNumberStop": 12, + "colNumberStop": 20, + "offsetStart": 122, + "offsetEnd": 138, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign fp::x (+ main::x))" + "content": "(assign fp::x main::x)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, + "lineNumberStart": 7, "colNumberStart": 4, - "lineNumberStop": 6, - "colNumberStop": 15, - "offsetStart": 56, - "offsetEnd": 67, - "sourceText": "return x + 1" + "lineNumberStop": 7, + "colNumberStop": 16, + "offsetStart": 77, + "offsetEnd": 89, + "sourceText": "return x + 1;" } }, "content": "(assign fp_ret (+ fp::x 1))" @@ -419,28 +653,22 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 11, - "colNumberStart": 15, - "lineNumberStop": 11, - "colNumberStop": 19, - "offsetStart": 112, - "offsetEnd": 116, - "sourceText": "fp(x)" + "lineNumberStart": 12, + "colNumberStart": 4, + "lineNumberStop": 12, + "colNumberStop": 20, + "offsetStart": 122, + "offsetEnd": 138, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign call_fp_ret97 (+ fp_ret))" + "content": "(assign call_fp_ret97 fp_ret)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -451,29 +679,29 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 12, - "colNumberStart": 8, - "lineNumberStop": 12, - "colNumberStop": 11, - "offsetStart": 127, - "offsetEnd": 130, - "sourceText": "f(x)" + "lineNumberStart": 13, + "colNumberStart": 4, + "lineNumberStop": 13, + "colNumberStop": 20, + "offsetStart": 144, + "offsetEnd": 160, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign f::x (+ main::x))" + "content": "(assign f::x main::x)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 2, + "lineNumberStart": 3, "colNumberStart": 4, - "lineNumberStop": 2, - "colNumberStop": 15, - "offsetStart": 19, - "offsetEnd": 30, - "sourceText": "return x - 1" + "lineNumberStop": 3, + "colNumberStop": 16, + "offsetStart": 40, + "offsetEnd": 52, + "sourceText": "return x - 1;" } }, "content": "(assign f_ret (+ f::x -1))" @@ -483,45 +711,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 12, - "colNumberStart": 8, - "lineNumberStop": 12, - "colNumberStop": 11, - "offsetStart": 127, - "offsetEnd": 130, - "sourceText": "f(x)" + "lineNumberStart": 13, + "colNumberStart": 4, + "lineNumberStop": 13, + "colNumberStop": 20, + "offsetStart": 144, + "offsetEnd": 160, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign call_f_ret98 (+ f_ret))" + "content": "(assign call_f_ret98 f_ret)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 12, - "colNumberStart": 15, - "lineNumberStop": 12, - "colNumberStop": 19, - "offsetStart": 134, - "offsetEnd": 138, - "sourceText": "fp(x)" + "lineNumberStart": 13, + "colNumberStart": 4, + "lineNumberStop": 13, + "colNumberStop": 20, + "offsetStart": 144, + "offsetEnd": 160, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign fp::x (+ main::x))" + "content": "(assign fp::x main::x)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, + "lineNumberStart": 7, "colNumberStart": 4, - "lineNumberStop": 6, - "colNumberStop": 15, - "offsetStart": 56, - "offsetEnd": 67, - "sourceText": "return x + 1" + "lineNumberStop": 7, + "colNumberStop": 16, + "offsetStart": 77, + "offsetEnd": 89, + "sourceText": "return x + 1;" } }, "content": "(assign fp_ret (+ fp::x 1))" @@ -531,28 +759,22 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 12, - "colNumberStart": 15, - "lineNumberStop": 12, - "colNumberStop": 19, - "offsetStart": 134, - "offsetEnd": 138, - "sourceText": "fp(x)" + "lineNumberStart": 13, + "colNumberStart": 4, + "lineNumberStop": 13, + "colNumberStop": 20, + "offsetStart": 144, + "offsetEnd": 160, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign call_fp_ret99 (+ fp_ret))" + "content": "(assign call_fp_ret99 fp_ret)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -563,29 +785,29 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 13, - "colNumberStart": 8, - "lineNumberStop": 13, - "colNumberStop": 11, - "offsetStart": 149, - "offsetEnd": 152, - "sourceText": "f(x)" + "lineNumberStart": 14, + "colNumberStart": 4, + "lineNumberStop": 14, + "colNumberStop": 20, + "offsetStart": 166, + "offsetEnd": 182, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign f::x (+ main::x))" + "content": "(assign f::x main::x)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 2, + "lineNumberStart": 3, "colNumberStart": 4, - "lineNumberStop": 2, - "colNumberStop": 15, - "offsetStart": 19, - "offsetEnd": 30, - "sourceText": "return x - 1" + "lineNumberStop": 3, + "colNumberStop": 16, + "offsetStart": 40, + "offsetEnd": 52, + "sourceText": "return x - 1;" } }, "content": "(assign f_ret (+ f::x -1))" @@ -595,45 +817,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 13, - "colNumberStart": 8, - "lineNumberStop": 13, - "colNumberStop": 11, - "offsetStart": 149, - "offsetEnd": 152, - "sourceText": "f(x)" + "lineNumberStart": 14, + "colNumberStart": 4, + "lineNumberStop": 14, + "colNumberStop": 20, + "offsetStart": 166, + "offsetEnd": 182, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign call_f_ret100 (+ f_ret))" + "content": "(assign call_f_ret100 f_ret)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 13, - "colNumberStart": 15, - "lineNumberStop": 13, - "colNumberStop": 19, - "offsetStart": 156, - "offsetEnd": 160, - "sourceText": "fp(x)" + "lineNumberStart": 14, + "colNumberStart": 4, + "lineNumberStop": 14, + "colNumberStop": 20, + "offsetStart": 166, + "offsetEnd": 182, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign fp::x (+ main::x))" + "content": "(assign fp::x main::x)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 6, + "lineNumberStart": 7, "colNumberStart": 4, - "lineNumberStop": 6, - "colNumberStop": 15, - "offsetStart": 56, - "offsetEnd": 67, - "sourceText": "return x + 1" + "lineNumberStop": 7, + "colNumberStop": 16, + "offsetStart": 77, + "offsetEnd": 89, + "sourceText": "return x + 1;" } }, "content": "(assign fp_ret (+ fp::x 1))" @@ -643,34 +865,40 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 13, - "colNumberStart": 15, - "lineNumberStop": 13, - "colNumberStop": 19, - "offsetStart": 156, - "offsetEnd": 160, - "sourceText": "fp(x)" + "lineNumberStart": 14, + "colNumberStart": 4, + "lineNumberStop": 14, + "colNumberStop": 20, + "offsetStart": 166, + "offsetEnd": 182, + "sourceText": "x \u003d f(x) - fp(x);" } }, - "content": "(assign call_fp_ret101 (+ fp_ret))" + "content": "(assign call_fp_ret101 fp_ret)" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, "content": "(assign main::x (+ call_f_ret100 (- call_fp_ret101)))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 29, + "offsetStart": 0, + "offsetEnd": 215, + "sourceText": "int main() {\n int x;\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n if(x \u003d\u003d -2) reach_error();\n}int x;\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n x \u003d f(x) - fp(x);\n if(x \u003d\u003d -2) reach_error();int x;x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);int f(int x) {\n return x - 1;\n}return x - 1;return x - 1;return x - 1;return x - 1;return x - 1;x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);int fp(int x) {\n return x + 1;\n}return x + 1;return x + 1;return x + 1;return x + 1;return x + 1;x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);int f(int x) {\n return x - 1;\n}return x - 1;return x - 1;return x - 1;return x - 1;return x - 1;x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);int fp(int x) {\n return x + 1;\n}return x + 1;return x + 1;return x + 1;return x + 1;return x + 1;x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);int f(int x) {\n return x - 1;\n}return x - 1;return x - 1;return x - 1;return x - 1;return x - 1;x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);x \u003d f(x) - fp(x);int fp(int x) {\n return x + 1;\n}return x + 1;return x + 1;return x + 1;return x + 1;return x + 1;x \u003d f(x) - fp(x);if(x \u003d\u003d -2) reach_error();if(x \u003d\u003d -2) reach_error();if(x \u003d\u003d -2) reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/22nondet.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/22nondet.c.json index 1ab02320c2..ee65fa7e58 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/22nondet.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/22nondet.c.json @@ -2,6 +2,94 @@ "name": "", "vars": [], "procedures": [ + { + "name": "reach_error", + "params": [ + { + "first": { + "type": "hu.bme.mit.theta.core.decl.VarDecl", + "value": { + "name": "reach_error_ret", + "type": "Int" + } + }, + "second": { + "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", + "value": "OUT" + } + } + ], + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } + ], + "locs": [ + { + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + }, + { + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}" + } + } + } + ], + "edges": [ + { + "source": "reach_error_init", + "target": "reach_error_final", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 1, + "colNumberStart": 0, + "lineNumberStop": 1, + "colNumberStop": 19, + "offsetStart": 0, + "offsetEnd": 19, + "sourceText": "void reach_error(){}void reach_error(){}void reach_error(){}" + } + } + } + ] + }, { "name": "main", "params": [ @@ -20,6 +108,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::i", "type": "Int" @@ -27,19 +119,94 @@ { "name": "call___VERIFIER_nondet_int_ret103", "type": "Int" + }, + { + "name": "call_reach_error_ret104", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_2176 ", - "__loc_2205 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 0, + "offsetStart": 57, + "offsetEnd": 200, + "sourceText": "int main() {\n int i \u003d 0;\n if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }\n if(i\u003d\u003d2) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 0, + "offsetStart": 57, + "offsetEnd": 200, + "sourceText": "int main() {\n int i \u003d 0;\n if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }\n if(i\u003d\u003d2) reach_error();\n}" + } + } + }, + { + "name": "__loc_2248", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 9, + "colNumberStop": 4, + "offsetStart": 89, + "offsetEnd": 170, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }" + } + } + }, + { + "name": "__loc_2273", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_2176", - "target": "__loc_2205", + "source": "__loc_2273", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -52,39 +219,76 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 33, - "offsetStart": 71, - "offsetEnd": 97, - "sourceText": "__VERIFIER_nondet_int() % 2" + "lineNumberStart": 10, + "colNumberStart": 4, + "lineNumberStop": 10, + "colNumberStop": 26, + "offsetStart": 176, + "offsetEnd": 198, + "sourceText": "if(i\u003d\u003d2) reach_error();" } }, - "content": "(assume (/\u003d (mod call___VERIFIER_nondet_int_ret103 2) 0))" - }, + "content": "((assume (\u003d (ite (\u003d main::i 2) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 26, + "offsetStart": 57, + "offsetEnd": 200, + "sourceText": "if(i\u003d\u003d2) reach_error();if(i\u003d\u003d2) reach_error();int main() {\n int i \u003d 0;\n if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }\n if(i\u003d\u003d2) reach_error();\n}" + } + } + }, + { + "source": "__loc_2273", + "target": "main_error", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 10, + "colNumberStart": 4, + "lineNumberStop": 10, + "colNumberStop": 26, + "offsetStart": 176, + "offsetEnd": 198, + "sourceText": "if(i\u003d\u003d2) reach_error();" } }, - "content": "(assign main::i 1)" + "content": "((assume (/\u003d (ite (\u003d main::i 2) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 10, + "colNumberStart": 4, + "lineNumberStop": 10, + "colNumberStop": 26, + "offsetStart": 176, + "offsetEnd": 198, + "sourceText": "if(i\u003d\u003d2) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { - "source": "__loc_2176", - "target": "__loc_2205", + "source": "__loc_2248", + "target": "__loc_2273", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -97,39 +301,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 33, - "offsetStart": 71, - "offsetEnd": 97, - "sourceText": "__VERIFIER_nondet_int() % 2" + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 9, + "colNumberStop": 4, + "offsetStart": 89, + "offsetEnd": 170, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }" } }, - "content": "(assume (\u003d (mod call___VERIFIER_nondet_int_ret103 2) 0))" + "content": "((assume (/\u003d (ite (\u003d (mod call___VERIFIER_nondet_int_ret103 2) 0) (mod call___VERIFIER_nondet_int_ret103 2) (ite (\u003e\u003d call___VERIFIER_nondet_int_ret103 0) (mod call___VERIFIER_nondet_int_ret103 2) (- (mod call___VERIFIER_nondet_int_ret103 2) 2))) 0)))[choiceType\u003dMAIN_PATH]" }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign main::i 2)" + "content": "(assign main::i 1)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 10, + "colNumberStop": 26, + "offsetStart": 0, + "offsetEnd": 198, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }{\n i \u003d 1;\n }i \u003d 1;i \u003d 1;i \u003d 1;if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }if(i\u003d\u003d2) reach_error();if(i\u003d\u003d2) reach_error();if(i\u003d\u003d2) reach_error();" + } } }, { - "source": "__loc_2205", - "target": "main_final", + "source": "__loc_2248", + "target": "__loc_2273", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -142,52 +352,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 9, - "colNumberStart": 7, + "lineNumberStart": 5, + "colNumberStart": 4, "lineNumberStop": 9, - "colNumberStop": 10, - "offsetStart": 158, - "offsetEnd": 161, - "sourceText": "i\u003d\u003d2" + "colNumberStop": 4, + "offsetStart": 89, + "offsetEnd": 170, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }" } }, - "content": "(assume (\u003d (ite (\u003d main::i 2) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_2205", - "target": "main_error", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "((assume (\u003d (ite (\u003d (mod call___VERIFIER_nondet_int_ret103 2) 0) (mod call___VERIFIER_nondet_int_ret103 2) (ite (\u003e\u003d call___VERIFIER_nondet_int_ret103 0) (mod call___VERIFIER_nondet_int_ret103 2) (- (mod call___VERIFIER_nondet_int_ret103 2) 2))) 0)))[choiceType\u003dALTERNATIVE_PATH]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 9, - "colNumberStart": 7, - "lineNumberStop": 9, - "colNumberStop": 10, - "offsetStart": 158, - "offsetEnd": 161, - "sourceText": "i\u003d\u003d2" + "sourceText": "" } }, - "content": "(assume (/\u003d (ite (\u003d main::i 2) 1 0) 0))" + "content": "(assign main::i 2)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 10, + "colNumberStop": 26, + "offsetStart": 0, + "offsetEnd": 198, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }{\n i \u003d 2;\n }i \u003d 2;i \u003d 2;i \u003d 2;if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }if(i\u003d\u003d2) reach_error();if(i\u003d\u003d2) reach_error();if(i\u003d\u003d2) reach_error();" + } } }, { "source": "main_init", - "target": "__loc_2176", + "target": "__loc_2248", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -200,12 +403,12 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 3, + "lineNumberStart": 4, "colNumberStart": 4, - "lineNumberStop": 3, + "lineNumberStop": 4, "colNumberStop": 13, - "offsetStart": 53, - "offsetEnd": 62, + "offsetStart": 74, + "offsetEnd": 83, "sourceText": "int i \u003d 0;" } }, @@ -216,13 +419,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 29, - "offsetStart": 71, - "offsetEnd": 93, - "sourceText": "__VERIFIER_nondet_int()" + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 9, + "colNumberStop": 4, + "offsetStart": 89, + "offsetEnd": 170, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }" } }, "content": "(havoc call___VERIFIER_nondet_int_ret103)" @@ -232,18 +435,30 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 4, - "colNumberStart": 7, - "lineNumberStop": 4, - "colNumberStop": 29, - "offsetStart": 71, - "offsetEnd": 93, - "sourceText": "__VERIFIER_nondet_int()" + "lineNumberStart": 5, + "colNumberStart": 4, + "lineNumberStop": 9, + "colNumberStop": 4, + "offsetStart": 89, + "offsetEnd": 170, + "sourceText": "if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }" } }, "content": "(assume (and (\u003e\u003d call___VERIFIER_nondet_int_ret103 -2147483648) (\u003c\u003d call___VERIFIER_nondet_int_ret103 2147483647)))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 11, + "colNumberStop": 26, + "offsetStart": 57, + "offsetEnd": 200, + "sourceText": "int main() {\n int i \u003d 0;\n if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }\n if(i\u003d\u003d2) reach_error();\n}int i \u003d 0;\n if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }\n if(i\u003d\u003d2) reach_error();int i \u003d 0;int i \u003d 0;int i \u003d 0;int i \u003d 0;if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }if(__VERIFIER_nondet_int() % 2) {\n i \u003d 1;\n } else {\n i \u003d 2;\n }" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/23overflow.c.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/23overflow.c.json index aa4cbfca7c..ac269dcc79 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/23overflow.c.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/23overflow.c.json @@ -20,20 +20,86 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::i", "type": "Int" + }, + { + "name": "call___VERIFIER_nondet_int_ret105", + "type": "Int" + }, + { + "name": "call_reach_error_ret106", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_2237 ", - "main_error {error}" + { + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 56, + "offsetEnd": 151, + "sourceText": "int main() {\n int i \u003d __VERIFIER_nondet_int();\n i \u003d i * 2;\n if(i \u003d\u003d 1) reach_error();\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 0, + "offsetStart": 56, + "offsetEnd": 151, + "sourceText": "int main() {\n int i \u003d __VERIFIER_nondet_int();\n i \u003d i * 2;\n if(i \u003d\u003d 1) reach_error();\n}" + } + } + }, + { + "name": "__loc_2304", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "main_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } ], "edges": [ { - "source": "__loc_2237", + "source": "__loc_2304", "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -48,21 +114,33 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 6, - "colNumberStop": 12, - "offsetStart": 128, - "offsetEnd": 133, - "sourceText": "i \u003d\u003d 1" + "colNumberStop": 28, + "offsetStart": 125, + "offsetEnd": 149, + "sourceText": "if(i \u003d\u003d 1) reach_error();" } }, - "content": "(assume (\u003d (ite (\u003d main::i 1) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003d main::i 1) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 28, + "offsetStart": 56, + "offsetEnd": 151, + "sourceText": "if(i \u003d\u003d 1) reach_error();if(i \u003d\u003d 1) reach_error();int main() {\n int i \u003d __VERIFIER_nondet_int();\n i \u003d i * 2;\n if(i \u003d\u003d 1) reach_error();\n}" + } } }, { - "source": "__loc_2237", + "source": "__loc_2304", "target": "main_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", @@ -77,22 +155,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 6, - "colNumberStart": 7, + "colNumberStart": 4, "lineNumberStop": 6, - "colNumberStop": 12, - "offsetStart": 128, - "offsetEnd": 133, - "sourceText": "i \u003d\u003d 1" + "colNumberStop": 28, + "offsetStart": 125, + "offsetEnd": 149, + "sourceText": "if(i \u003d\u003d 1) reach_error();" } }, - "content": "(assume (/\u003d (ite (\u003d main::i 1) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003d main::i 1) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 6, + "colNumberStart": 4, + "lineNumberStop": 6, + "colNumberStop": 28, + "offsetStart": 125, + "offsetEnd": 149, + "sourceText": "if(i \u003d\u003d 1) reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { "source": "main_init", - "target": "__loc_2237", + "target": "__loc_2304", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -106,12 +196,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 12, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 34, - "offsetStart": 81, - "offsetEnd": 103, - "sourceText": "__VERIFIER_nondet_int()" + "colNumberStop": 35, + "offsetStart": 73, + "offsetEnd": 104, + "sourceText": "int i \u003d __VERIFIER_nondet_int();" } }, "content": "(havoc main::i)" @@ -122,12 +212,12 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 4, - "colNumberStart": 12, + "colNumberStart": 4, "lineNumberStop": 4, - "colNumberStop": 34, - "offsetStart": 81, - "offsetEnd": 103, - "sourceText": "__VERIFIER_nondet_int()" + "colNumberStop": 35, + "offsetStart": 73, + "offsetEnd": 104, + "sourceText": "int i \u003d __VERIFIER_nondet_int();" } }, "content": "(assume (and (\u003e\u003d main::i -2147483648) (\u003c\u003d main::i 2147483647)))" @@ -137,18 +227,24 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, "content": "(assign main::i (* 2 main::i))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 7, + "colNumberStop": 35, + "offsetStart": 0, + "offsetEnd": 151, + "sourceText": "int main() {\n int i \u003d __VERIFIER_nondet_int();\n i \u003d i * 2;\n if(i \u003d\u003d 1) reach_error();\n}int i \u003d __VERIFIER_nondet_int();\n i \u003d i * 2;\n if(i \u003d\u003d 1) reach_error();int i \u003d __VERIFIER_nondet_int();int i \u003d __VERIFIER_nondet_int();int i \u003d __VERIFIER_nondet_int();int i \u003d __VERIFIER_nondet_int();int i \u003d __VERIFIER_nondet_int();int i \u003d __VERIFIER_nondet_int();i \u003d i * 2;i \u003d i * 2;i \u003d i * 2;if(i \u003d\u003d 1) reach_error();if(i \u003d\u003d 1) reach_error();if(i \u003d\u003d 1) reach_error();" + } } } ] diff --git a/subprojects/xcfa/xcfa-cli/src/test/resources/json/dekker.i.json b/subprojects/xcfa/xcfa-cli/src/test/resources/json/dekker.i.json index 928ba9be88..6cf9c1d326 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/resources/json/dekker.i.json +++ b/subprojects/xcfa/xcfa-cli/src/test/resources/json/dekker.i.json @@ -66,46 +66,91 @@ } ], "vars": [ + { + "name": "assume_abort_if_not_ret", + "type": "Int" + }, { "name": "assume_abort_if_not::cond", "type": "Int" + }, + { + "name": "call_abort_ret0", + "type": "Int" } ], "locs": [ - "assume_abort_if_not_init {init}", - "assume_abort_if_not_final {final}", - "__loc_2 ", - "__loc_7 ", - "__loc_13 " - ], - "edges": [ { - "source": "__loc_2", - "target": "assume_abort_if_not_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "assume_abort_if_not_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 0, + "offsetStart": 25, + "offsetEnd": 85, + "sourceText": "void assume_abort_if_not(int cond) {\n if(!cond) {abort();}\n}" + } } }, { - "source": "assume_abort_if_not_init", - "target": "__loc_7", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "assume_abort_if_not_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 0, + "offsetStart": 25, + "offsetEnd": 85, + "sourceText": "void assume_abort_if_not(int cond) {\n if(!cond) {abort();}\n}" + } + } + }, + { + "name": "__loc_8", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } } }, { - "source": "__loc_7", - "target": "__loc_13", + "name": "__loc_14", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 13, + "lineNumberStop": 3, + "colNumberStop": 20, + "offsetStart": 75, + "offsetEnd": 82, + "sourceText": "abort();" + } + } + } + ], + "edges": [ + { + "source": "__loc_14", + "target": "assume_abort_if_not_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -119,22 +164,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 3, - "colNumberStart": 5, + "colNumberStart": 13, "lineNumberStop": 3, - "colNumberStop": 9, - "offsetStart": 67, - "offsetEnd": 71, - "sourceText": "!cond" + "colNumberStop": 20, + "offsetStart": 75, + "offsetEnd": 82, + "sourceText": "abort();" } }, - "content": "(assume (/\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0))" + "content": "(assume false)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 13, + "lineNumberStop": 3, + "colNumberStop": 20, + "offsetStart": 75, + "offsetEnd": 82, + "sourceText": "abort();" + } } }, { - "source": "__loc_7", - "target": "__loc_2", + "source": "__loc_8", + "target": "assume_abort_if_not_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -148,22 +205,58 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 3, - "colNumberStart": 5, + "colNumberStart": 2, "lineNumberStop": 3, - "colNumberStop": 9, - "offsetStart": 67, - "offsetEnd": 71, - "sourceText": "!cond" + "colNumberStop": 21, + "offsetStart": 64, + "offsetEnd": 83, + "sourceText": "if(!cond) {abort();}" } }, - "content": "(assume (\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 21, + "offsetStart": 25, + "offsetEnd": 85, + "sourceText": "if(!cond) {abort();}if(!cond) {abort();}void assume_abort_if_not(int cond) {\n if(!cond) {abort();}\n}" + } } }, { - "source": "__loc_13", - "target": "assume_abort_if_not_final", + "source": "assume_abort_if_not_init", + "target": "__loc_8", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 4, + "colNumberStop": 21, + "offsetStart": 25, + "offsetEnd": 85, + "sourceText": "void assume_abort_if_not(int cond) {\n if(!cond) {abort();}\n}if(!cond) {abort();}if(!cond) {abort();}if(!cond) {abort();}if(!cond) {abort();}" + } + } + }, + { + "source": "__loc_8", + "target": "__loc_14", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -174,12 +267,32 @@ { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 2, + "lineNumberStop": 3, + "colNumberStop": 21, + "offsetStart": 64, + "offsetEnd": 83, + "sourceText": "if(!cond) {abort();}" + } }, - "content": "(assume false)" + "content": "((assume (/\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 2, + "lineNumberStop": 3, + "colNumberStop": 21, + "offsetStart": 64, + "offsetEnd": 83, + "sourceText": "if(!cond) {abort();}{abort();}abort();abort();abort();" + } } } ] @@ -201,28 +314,54 @@ } } ], - "vars": [], - "locs": [ - "reach_error_init {init}", - "reach_error_final {final}", - "__loc_37 " + "vars": [ + { + "name": "reach_error_ret", + "type": "Int" + } ], - "edges": [ + "locs": [ { - "source": "__loc_37", - "target": "reach_error_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] + "name": "reach_error_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 16, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 158, + "offsetStart": 669, + "offsetEnd": 827, + "sourceText": "void reach_error() { ((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); })); }" + } } }, + { + "name": "reach_error_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 16, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 158, + "offsetStart": 669, + "offsetEnd": 827, + "sourceText": "void reach_error() { ((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); })); }" + } + } + } + ], + "edges": [ { "source": "reach_error_init", - "target": "__loc_37", + "target": "reach_error_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -230,6 +369,18 @@ "content": {} }, "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 16, + "colNumberStart": 0, + "lineNumberStop": 16, + "colNumberStop": 158, + "offsetStart": 669, + "offsetEnd": 827, + "sourceText": "void reach_error() { ((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); })); }((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); }));void reach_error() { ((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail (\"0\", \"dekker.c\", 7, __extension__ __PRETTY_FUNCTION__); })); }" + } } } ] @@ -245,75 +396,557 @@ "type": "Int" } }, - "second": { - "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", - "value": "OUT" - } - }, - { - "first": { - "type": "hu.bme.mit.theta.core.decl.VarDecl", - "value": { - "name": "thr1::_", - "type": "Int" + "second": { + "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", + "value": "OUT" + } + }, + { + "first": { + "type": "hu.bme.mit.theta.core.decl.VarDecl", + "value": { + "name": "thr1::_", + "type": "Int" + } + }, + "second": { + "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", + "value": "IN" + } + } + ], + "vars": [ + { + "name": "thr1_ret", + "type": "Int" + }, + { + "name": "thr1::_", + "type": "Int" + }, + { + "name": "thr1::f2", + "type": "Int" + }, + { + "name": "thr1::while1::t", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret1", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret2", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret3", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret4", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret5", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret6", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret7", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret8", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret9", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret10", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret11", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret12", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret13", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret14", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret15", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret16", + "type": "Int" + }, + { + "name": "call_reach_error_ret17", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret18", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret19", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret20", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret21", + "type": "Int" + } + ], + "locs": [ + { + "name": "thr1_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 707, + "colNumberStart": 0, + "lineNumberStop": 747, + "colNumberStop": 0, + "offsetStart": 30501, + "offsetEnd": 31579, + "sourceText": "void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f2 \u003d flag2;\n __VERIFIER_atomic_end();\n while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }\n x \u003d 0;\n if (!(x\u003c\u003d0)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;\n}" + } + } + }, + { + "name": "thr1_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 707, + "colNumberStart": 0, + "lineNumberStop": 747, + "colNumberStop": 0, + "offsetStart": 30501, + "offsetEnd": 31579, + "sourceText": "void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f2 \u003d flag2;\n __VERIFIER_atomic_end();\n while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }\n x \u003d 0;\n if (!(x\u003c\u003d0)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;\n}" + } + } + }, + { + "name": "__loc_39", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 708, + "colNumberStart": 4, + "lineNumberStop": 708, + "colNumberStop": 29, + "offsetStart": 30527, + "offsetEnd": 30552, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_58", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 711, + "colNumberStart": 4, + "lineNumberStop": 711, + "colNumberStop": 29, + "offsetStart": 30602, + "offsetEnd": 30627, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_79", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_85", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 715, + "colNumberStart": 8, + "lineNumberStop": 715, + "colNumberStop": 33, + "offsetStart": 30708, + "offsetEnd": 30733, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_106", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_112", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 719, + "colNumberStart": 12, + "lineNumberStop": 719, + "colNumberStop": 37, + "offsetStart": 30824, + "offsetEnd": 30849, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_131", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 722, + "colNumberStart": 12, + "lineNumberStop": 722, + "colNumberStop": 37, + "offsetStart": 30923, + "offsetEnd": 30948, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_153", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_159", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 726, + "colNumberStart": 16, + "lineNumberStop": 726, + "colNumberStop": 41, + "offsetStart": 31054, + "offsetEnd": 31079, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_180", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 730, + "colNumberStart": 12, + "lineNumberStop": 730, + "colNumberStop": 37, + "offsetStart": 31175, + "offsetEnd": 31200, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_199", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 734, + "colNumberStart": 8, + "lineNumberStop": 734, + "colNumberStop": 33, + "offsetStart": 31280, + "offsetEnd": 31305, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_221", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 738, + "colNumberStart": 4, + "lineNumberStop": 738, + "colNumberStop": 9, + "offsetStart": 31370, + "offsetEnd": 31375, + "sourceText": "x \u003d 0;" + } + } + }, + { + "name": "__loc_233", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_244", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 740, + "colNumberStart": 4, + "lineNumberStop": 740, + "colNumberStop": 29, + "offsetStart": 31420, + "offsetEnd": 31445, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_263", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 743, + "colNumberStart": 4, + "lineNumberStop": 743, + "colNumberStop": 29, + "offsetStart": 31494, + "offsetEnd": 31519, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "thr1_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } + ], + "edges": [ + { + "source": "thr1_init", + "target": "__loc_39", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 707, + "colNumberStart": 0, + "lineNumberStop": 747, + "colNumberStop": 29, + "offsetStart": 30501, + "offsetEnd": 31579, + "sourceText": "void *thr1(void *_) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f2 \u003d flag2;\n __VERIFIER_atomic_end();\n while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }\n x \u003d 0;\n if (!(x\u003c\u003d0)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;\n}__VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f2 \u003d flag2;\n __VERIFIER_atomic_end();\n while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }\n x \u003d 0;\n if (!(x\u003c\u003d0)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } + } + }, + { + "source": "__loc_39", + "target": "__loc_58", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 708, + "colNumberStart": 4, + "lineNumberStop": 708, + "colNumberStop": 29, + "offsetStart": 30527, + "offsetEnd": 30552, + "sourceText": "__VERIFIER_atomic_begin();" + } + }, + "content": "F[ATOMIC_BEGIN]" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + }, + "content": "(assign flag1 1)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 710, + "colNumberStart": 4, + "lineNumberStop": 710, + "colNumberStop": 27, + "offsetStart": 30573, + "offsetEnd": 30596, + "sourceText": "__VERIFIER_atomic_end();" + } + }, + "content": "F[ATOMIC_END]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 708, + "colNumberStart": 4, + "lineNumberStop": 711, + "colNumberStop": 29, + "offsetStart": 30527, + "offsetEnd": 30627, + "sourceText": "__VERIFIER_atomic_begin();flag1 \u003d 1;flag1 \u003d 1;flag1 \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" } - }, - "second": { - "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", - "value": "IN" } - } - ], - "vars": [ - { - "name": "thr1::f2", - "type": "Int" - }, - { - "name": "thr1::while1::t", - "type": "Int" }, { - "name": "thr1_ret", - "type": "Int" - } - ], - "locs": [ - "thr1_init {init}", - "thr1_final {final}", - "__loc_42 ", - "__loc_63 ", - "__loc_84 ", - "__loc_90 ", - "__loc_111 ", - "__loc_117 ", - "__loc_138 ", - "__loc_162 ", - "__loc_168 ", - "__loc_191 ", - "__loc_212 ", - "__loc_238 ", - "__loc_250 ", - "__loc_261 ", - "__loc_282 ", - "thr1_error {error}" - ], - "edges": [ - { - "source": "thr1_init", - "target": "__loc_42", + "source": "__loc_79", + "target": "__loc_85", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", "content": {} }, - "labels": [] + "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 4, + "lineNumberStop": 737, + "colNumberStop": 4, + "offsetStart": 30682, + "offsetEnd": 31364, + "sourceText": "while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }" + } + }, + "content": "((assume (/\u003d (ite (\u003e\u003d thr1::f2 1) 1 0) 0)))[choiceType\u003dMAIN_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 4, + "lineNumberStop": 737, + "colNumberStop": 33, + "offsetStart": 30682, + "offsetEnd": 31364, + "sourceText": "while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }{\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_84", - "target": "__loc_90", + "source": "__loc_85", + "target": "__loc_106", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -321,28 +954,72 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 715, + "colNumberStart": 8, + "lineNumberStop": 715, + "colNumberStop": 33, + "offsetStart": 30708, + "offsetEnd": 30733, + "sourceText": "__VERIFIER_atomic_begin();" + } + }, + "content": "F[ATOMIC_BEGIN]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 714, - "colNumberStart": 11, - "lineNumberStop": 714, - "colNumberStop": 17, - "offsetStart": 30689, - "offsetEnd": 30695, - "sourceText": "f2 \u003e\u003d 1" + "lineNumberStart": 716, + "colNumberStart": 8, + "lineNumberStop": 716, + "colNumberStop": 20, + "offsetStart": 30743, + "offsetEnd": 30755, + "sourceText": "int t \u003d turn;" + } + }, + "content": "(assign thr1::while1::t turn)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 717, + "colNumberStart": 8, + "lineNumberStop": 717, + "colNumberStop": 31, + "offsetStart": 30765, + "offsetEnd": 30788, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "(assume (/\u003d (ite (\u003e\u003d thr1::f2 1) 1 0) 0))" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 715, + "colNumberStart": 8, + "lineNumberStop": 733, + "colNumberStop": 33, + "offsetStart": 30708, + "offsetEnd": 31270, + "sourceText": "__VERIFIER_atomic_begin();int t \u003d turn;int t \u003d turn;int t \u003d turn;int t \u003d turn;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_111", - "target": "__loc_117", + "source": "__loc_106", + "target": "__loc_112", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -356,22 +1033,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 718, - "colNumberStart": 12, - "lineNumberStop": 718, - "colNumberStop": 17, - "offsetStart": 30802, - "offsetEnd": 30807, - "sourceText": "t !\u003d 0" + "colNumberStart": 8, + "lineNumberStop": 733, + "colNumberStop": 8, + "offsetStart": 30798, + "offsetEnd": 31270, + "sourceText": "if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (/\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0))" + "content": "((assume (/\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 718, + "colNumberStart": 8, + "lineNumberStop": 733, + "colNumberStop": 37, + "offsetStart": 30798, + "offsetEnd": 31270, + "sourceText": "if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }{\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_162", - "target": "__loc_168", + "source": "__loc_112", + "target": "__loc_131", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -379,28 +1068,66 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 719, + "colNumberStart": 12, + "lineNumberStop": 719, + "colNumberStop": 37, + "offsetStart": 30824, + "offsetEnd": 30849, + "sourceText": "__VERIFIER_atomic_begin();" + } + }, + "content": "F[ATOMIC_BEGIN]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 725, - "colNumberStart": 19, - "lineNumberStop": 725, - "colNumberStop": 24, - "offsetStart": 31028, - "offsetEnd": 31033, - "sourceText": "t !\u003d 0" + "sourceText": "" + } + }, + "content": "(assign flag1 0)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 721, + "colNumberStart": 12, + "lineNumberStop": 721, + "colNumberStop": 35, + "offsetStart": 30886, + "offsetEnd": 30909, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "(assume (/\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0))" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 719, + "colNumberStart": 12, + "lineNumberStop": 722, + "colNumberStop": 37, + "offsetStart": 30824, + "offsetEnd": 30948, + "sourceText": "__VERIFIER_atomic_begin();flag1 \u003d 0;flag1 \u003d 0;flag1 \u003d 0;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_162", - "target": "__loc_191", + "source": "__loc_153", + "target": "__loc_159", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -422,14 +1149,26 @@ "sourceText": "while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0))" + "content": "((assume (/\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 725, + "colNumberStart": 12, + "lineNumberStop": 729, + "colNumberStop": 41, + "offsetStart": 31021, + "offsetEnd": 31160, + "sourceText": "while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }{\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_111", - "target": "__loc_212", + "source": "__loc_153", + "target": "__loc_180", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -442,23 +1181,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 718, + "lineNumberStart": 725, "colNumberStart": 12, - "lineNumberStop": 718, - "colNumberStop": 17, - "offsetStart": 30802, - "offsetEnd": 30807, - "sourceText": "t !\u003d 0" + "lineNumberStop": 729, + "colNumberStop": 12, + "offsetStart": 31021, + "offsetEnd": 31160, + "sourceText": "while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0))" + "content": "((assume (\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 725, + "colNumberStart": 12, + "lineNumberStop": 730, + "colNumberStop": 37, + "offsetStart": 31021, + "offsetEnd": 31200, + "sourceText": "while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_84", - "target": "__loc_238", + "source": "__loc_79", + "target": "__loc_221", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -480,14 +1231,26 @@ "sourceText": "while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (\u003d (ite (\u003e\u003d thr1::f2 1) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003e\u003d thr1::f2 1) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 4, + "lineNumberStop": 738, + "colNumberStop": 9, + "offsetStart": 30682, + "offsetEnd": 31375, + "sourceText": "while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }x \u003d 0;x \u003d 0;x \u003d 0;" + } } }, { - "source": "__loc_238", - "target": "__loc_250", + "source": "__loc_221", + "target": "__loc_233", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -500,23 +1263,29 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, "content": "(assign x 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 739, + "colNumberStop": 37, + "offsetStart": 0, + "offsetEnd": 31414, + "sourceText": "if (!(x\u003c\u003d0)) ERROR: reach_error();if (!(x\u003c\u003d0)) ERROR: reach_error();if (!(x\u003c\u003d0)) ERROR: reach_error();if (!(x\u003c\u003d0)) ERROR: reach_error();if (!(x\u003c\u003d0)) ERROR: reach_error();" + } } }, { - "source": "__loc_250", - "target": "__loc_261", + "source": "__loc_233", + "target": "thr1_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -530,22 +1299,75 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 739, - "colNumberStart": 8, + "colNumberStart": 4, + "lineNumberStop": 739, + "colNumberStop": 37, + "offsetStart": 31381, + "offsetEnd": 31414, + "sourceText": "if (!(x\u003c\u003d0)) ERROR: reach_error();" + } + }, + "content": "((assume (/\u003d (ite (\u003d (ite (\u003c\u003d x 0) 1 0) 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" + } + ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 739, + "colNumberStart": 4, + "lineNumberStop": 739, + "colNumberStop": 37, + "offsetStart": 31381, + "offsetEnd": 31414, + "sourceText": "if (!(x\u003c\u003d0)) ERROR: reach_error();ERROR: reach_error();reach_error();reach_error();reach_error();reach_error();" + } + } + }, + { + "source": "__loc_233", + "target": "__loc_244", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 739, + "colNumberStart": 4, "lineNumberStop": 739, - "colNumberStop": 14, - "offsetStart": 31385, - "offsetEnd": 31391, - "sourceText": "!(x\u003c\u003d0)" + "colNumberStop": 37, + "offsetStart": 31381, + "offsetEnd": 31414, + "sourceText": "if (!(x\u003c\u003d0)) ERROR: reach_error();" } }, - "content": "(assume (\u003d (ite (\u003d (ite (\u003c\u003d x 0) 1 0) 0) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003d (ite (\u003c\u003d x 0) 1 0) 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 739, + "colNumberStart": 4, + "lineNumberStop": 740, + "colNumberStop": 37, + "offsetStart": 31381, + "offsetEnd": 31445, + "sourceText": "if (!(x\u003c\u003d0)) ERROR: reach_error();if (!(x\u003c\u003d0)) ERROR: reach_error();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_42", - "target": "__loc_63", + "source": "__loc_244", + "target": "__loc_263", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -558,13 +1380,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 708, + "lineNumberStart": 740, "colNumberStart": 4, - "lineNumberStop": 708, - "colNumberStop": 28, - "offsetStart": 30527, - "offsetEnd": 30551, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStop": 740, + "colNumberStop": 29, + "offsetStart": 31420, + "offsetEnd": 31445, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -574,39 +1396,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign flag1 1)" + "content": "(assign turn 1)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 710, + "lineNumberStart": 742, "colNumberStart": 4, - "lineNumberStop": 710, - "colNumberStop": 26, - "offsetStart": 30573, - "offsetEnd": 30595, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStop": 742, + "colNumberStop": 27, + "offsetStart": 31465, + "offsetEnd": 31488, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 740, + "colNumberStart": 4, + "lineNumberStop": 743, + "colNumberStop": 29, + "offsetStart": 31420, + "offsetEnd": 31519, + "sourceText": "__VERIFIER_atomic_begin();turn \u003d 1;turn \u003d 1;turn \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_63", - "target": "__loc_84", + "source": "__loc_263", + "target": "thr1_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -619,13 +1447,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 711, + "lineNumberStart": 743, "colNumberStart": 4, - "lineNumberStop": 711, - "colNumberStop": 28, - "offsetStart": 30602, - "offsetEnd": 30626, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStop": 743, + "colNumberStop": 29, + "offsetStart": 31494, + "offsetEnd": 31519, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -635,39 +1463,61 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 712, - "colNumberStart": 4, - "lineNumberStop": 712, - "colNumberStop": 18, - "offsetStart": 30633, - "offsetEnd": 30647, - "sourceText": "int f2 \u003d flag2;" + "sourceText": "" } }, - "content": "(assign thr1::f2 flag2)" + "content": "(assign flag1 0)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 713, + "lineNumberStart": 745, "colNumberStart": 4, - "lineNumberStop": 713, - "colNumberStop": 26, - "offsetStart": 30653, - "offsetEnd": 30675, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStop": 745, + "colNumberStop": 27, + "offsetStart": 31540, + "offsetEnd": 31563, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 746, + "colNumberStart": 4, + "lineNumberStop": 746, + "colNumberStop": 12, + "offsetStart": 31569, + "offsetEnd": 31577, + "sourceText": "return 0;" + } + }, + "content": "(assign thr1_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 743, + "colNumberStart": 4, + "lineNumberStop": 746, + "colNumberStop": 29, + "offsetStart": 31494, + "offsetEnd": 31577, + "sourceText": "__VERIFIER_atomic_begin();flag1 \u003d 0;flag1 \u003d 0;flag1 \u003d 0;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();return 0;return 0;return 0;return 0;" + } } }, { - "source": "__loc_90", - "target": "__loc_111", + "source": "__loc_58", + "target": "__loc_79", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -680,13 +1530,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 715, - "colNumberStart": 8, - "lineNumberStop": 715, - "colNumberStop": 32, - "offsetStart": 30708, - "offsetEnd": 30732, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 711, + "colNumberStart": 4, + "lineNumberStop": 711, + "colNumberStop": 29, + "offsetStart": 30602, + "offsetEnd": 30627, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -696,39 +1546,51 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 716, - "colNumberStart": 8, - "lineNumberStop": 716, - "colNumberStop": 20, - "offsetStart": 30743, - "offsetEnd": 30755, - "sourceText": "int t \u003d turn;" + "lineNumberStart": 712, + "colNumberStart": 4, + "lineNumberStop": 712, + "colNumberStop": 18, + "offsetStart": 30633, + "offsetEnd": 30647, + "sourceText": "int f2 \u003d flag2;" } }, - "content": "(assign thr1::while1::t turn)" + "content": "(assign thr1::f2 flag2)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 717, - "colNumberStart": 8, - "lineNumberStop": 717, - "colNumberStop": 30, - "offsetStart": 30765, - "offsetEnd": 30787, - "sourceText": "__VERIFIER_atomic_end()" + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 713, + "colNumberStart": 4, + "lineNumberStop": 713, + "colNumberStop": 27, + "offsetStart": 30653, + "offsetEnd": 30676, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 711, + "colNumberStart": 4, + "lineNumberStop": 737, + "colNumberStop": 29, + "offsetStart": 30602, + "offsetEnd": 31364, + "sourceText": "__VERIFIER_atomic_begin();int f2 \u003d flag2;int f2 \u003d flag2;int f2 \u003d flag2;int f2 \u003d flag2;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_261", - "target": "__loc_282", + "source": "__loc_199", + "target": "__loc_79", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -741,13 +1603,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 740, - "colNumberStart": 4, - "lineNumberStop": 740, - "colNumberStop": 28, - "offsetStart": 31420, - "offsetEnd": 31444, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 734, + "colNumberStart": 8, + "lineNumberStop": 734, + "colNumberStop": 33, + "offsetStart": 31280, + "offsetEnd": 31305, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -757,39 +1619,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign turn 1)" + "content": "(assign thr1::f2 flag2)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 742, - "colNumberStart": 4, - "lineNumberStop": 742, - "colNumberStop": 26, - "offsetStart": 31465, - "offsetEnd": 31487, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 736, + "colNumberStart": 8, + "lineNumberStop": 736, + "colNumberStop": 31, + "offsetStart": 31335, + "offsetEnd": 31358, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 714, + "colNumberStart": 4, + "lineNumberStop": 737, + "colNumberStop": 33, + "offsetStart": 30682, + "offsetEnd": 31364, + "sourceText": "__VERIFIER_atomic_begin();f2 \u003d flag2;f2 \u003d flag2;f2 \u003d flag2;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }while (f2 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f2 \u003d flag2;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_117", - "target": "__loc_138", + "source": "__loc_106", + "target": "__loc_199", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -797,60 +1665,40 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 719, - "colNumberStart": 12, - "lineNumberStop": 719, - "colNumberStop": 36, - "offsetStart": 30824, - "offsetEnd": 30848, - "sourceText": "__VERIFIER_atomic_begin()" - } - }, - "content": "F[ATOMIC_BEGIN]" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" - } - }, - "content": "(assign flag1 0)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 721, - "colNumberStart": 12, - "lineNumberStop": 721, - "colNumberStop": 34, - "offsetStart": 30886, - "offsetEnd": 30908, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 718, + "colNumberStart": 8, + "lineNumberStop": 733, + "colNumberStop": 8, + "offsetStart": 30798, + "offsetEnd": 31270, + "sourceText": "if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }" } }, - "content": "F[ATOMIC_END]" + "content": "((assume (\u003d (ite (/\u003d thr1::while1::t 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 718, + "colNumberStart": 8, + "lineNumberStop": 734, + "colNumberStop": 33, + "offsetStart": 30798, + "offsetEnd": 31305, + "sourceText": "if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_212", - "target": "__loc_84", + "source": "__loc_180", + "target": "__loc_199", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -863,13 +1711,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 734, - "colNumberStart": 8, - "lineNumberStop": 734, - "colNumberStop": 32, - "offsetStart": 31280, - "offsetEnd": 31304, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 730, + "colNumberStart": 12, + "lineNumberStop": 730, + "colNumberStop": 37, + "offsetStart": 31175, + "offsetEnd": 31200, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -879,39 +1727,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign thr1::f2 flag2)" + "content": "(assign flag1 1)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 736, - "colNumberStart": 8, - "lineNumberStop": 736, - "colNumberStop": 30, - "offsetStart": 31335, - "offsetEnd": 31357, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 732, + "colNumberStart": 12, + "lineNumberStop": 732, + "colNumberStop": 35, + "offsetStart": 31237, + "offsetEnd": 31260, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 718, + "colNumberStart": 8, + "lineNumberStop": 734, + "colNumberStop": 37, + "offsetStart": 30798, + "offsetEnd": 31305, + "sourceText": "__VERIFIER_atomic_begin();flag1 \u003d 1;flag1 \u003d 1;flag1 \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();if (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n flag1 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag1 \u003d 1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_138", - "target": "__loc_162", + "source": "__loc_131", + "target": "__loc_153", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -927,10 +1781,10 @@ "lineNumberStart": 722, "colNumberStart": 12, "lineNumberStop": 722, - "colNumberStop": 36, + "colNumberStop": 37, "offsetStart": 30923, - "offsetEnd": 30947, - "sourceText": "__VERIFIER_atomic_begin()" + "offsetEnd": 30948, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -940,12 +1794,6 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -959,20 +1807,32 @@ "lineNumberStart": 724, "colNumberStart": 12, "lineNumberStop": 724, - "colNumberStop": 34, + "colNumberStop": 35, "offsetStart": 30984, - "offsetEnd": 31006, - "sourceText": "__VERIFIER_atomic_end()" + "offsetEnd": 31007, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 722, + "colNumberStart": 12, + "lineNumberStop": 729, + "colNumberStop": 37, + "offsetStart": 30923, + "offsetEnd": 31160, + "sourceText": "__VERIFIER_atomic_begin();t \u003d turn;t \u003d turn;t \u003d turn;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_168", - "target": "__loc_162", + "source": "__loc_159", + "target": "__loc_153", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -988,10 +1848,10 @@ "lineNumberStart": 726, "colNumberStart": 16, "lineNumberStop": 726, - "colNumberStop": 40, + "colNumberStop": 41, "offsetStart": 31054, - "offsetEnd": 31078, - "sourceText": "__VERIFIER_atomic_begin()" + "offsetEnd": 31079, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1001,12 +1861,6 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -1020,20 +1874,485 @@ "lineNumberStart": 728, "colNumberStart": 16, "lineNumberStop": 728, - "colNumberStop": 38, + "colNumberStop": 39, "offsetStart": 31123, - "offsetEnd": 31145, - "sourceText": "__VERIFIER_atomic_end()" + "offsetEnd": 31146, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 725, + "colNumberStart": 12, + "lineNumberStop": 729, + "colNumberStop": 41, + "offsetStart": 31021, + "offsetEnd": 31160, + "sourceText": "__VERIFIER_atomic_begin();t \u003d turn;t \u003d turn;t \u003d turn;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 0) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" + } + } + } + ] + }, + { + "name": "thr2", + "params": [ + { + "first": { + "type": "hu.bme.mit.theta.core.decl.VarDecl", + "value": { + "name": "thr2_ret", + "type": "Int" + } + }, + "second": { + "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", + "value": "OUT" + } + }, + { + "first": { + "type": "hu.bme.mit.theta.core.decl.VarDecl", + "value": { + "name": "thr2::_", + "type": "Int" + } + }, + "second": { + "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", + "value": "IN" + } + } + ], + "vars": [ + { + "name": "thr2_ret", + "type": "Int" + }, + { + "name": "thr2::_", + "type": "Int" + }, + { + "name": "thr2::f1", + "type": "Int" + }, + { + "name": "thr2::while5::t", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret22", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret23", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret24", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret25", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret26", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret27", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret28", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret29", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret30", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret31", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret32", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret33", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret34", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret35", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret36", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret37", + "type": "Int" + }, + { + "name": "call_reach_error_ret38", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret39", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret40", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_begin_ret41", + "type": "Int" + }, + { + "name": "call___VERIFIER_atomic_end_ret42", + "type": "Int" + } + ], + "locs": [ + { + "name": "thr2_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 748, + "colNumberStart": 0, + "lineNumberStop": 788, + "colNumberStop": 0, + "offsetStart": 31581, + "offsetEnd": 32659, + "sourceText": "void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f1 \u003d flag1;\n __VERIFIER_atomic_end();\n while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }\n x \u003d 1;\n if (!(x\u003e\u003d1)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;\n}" + } + } + }, + { + "name": "thr2_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 748, + "colNumberStart": 0, + "lineNumberStop": 788, + "colNumberStop": 0, + "offsetStart": 31581, + "offsetEnd": 32659, + "sourceText": "void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f1 \u003d flag1;\n __VERIFIER_atomic_end();\n while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }\n x \u003d 1;\n if (!(x\u003e\u003d1)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;\n}" + } + } + }, + { + "name": "__loc_290", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 749, + "colNumberStart": 4, + "lineNumberStop": 749, + "colNumberStop": 29, + "offsetStart": 31607, + "offsetEnd": 31632, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_309", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 752, + "colNumberStart": 4, + "lineNumberStop": 752, + "colNumberStop": 29, + "offsetStart": 31682, + "offsetEnd": 31707, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_330", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_336", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 756, + "colNumberStart": 8, + "lineNumberStop": 756, + "colNumberStop": 33, + "offsetStart": 31788, + "offsetEnd": 31813, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_357", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_363", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 760, + "colNumberStart": 12, + "lineNumberStop": 760, + "colNumberStop": 37, + "offsetStart": 31904, + "offsetEnd": 31929, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_382", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 763, + "colNumberStart": 12, + "lineNumberStop": 763, + "colNumberStop": 37, + "offsetStart": 32003, + "offsetEnd": 32028, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_404", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_410", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 767, + "colNumberStart": 16, + "lineNumberStop": 767, + "colNumberStop": 41, + "offsetStart": 32134, + "offsetEnd": 32159, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_431", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 771, + "colNumberStart": 12, + "lineNumberStop": 771, + "colNumberStop": 37, + "offsetStart": 32255, + "offsetEnd": 32280, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_450", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 775, + "colNumberStart": 8, + "lineNumberStop": 775, + "colNumberStop": 33, + "offsetStart": 32360, + "offsetEnd": 32385, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_472", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 779, + "colNumberStart": 4, + "lineNumberStop": 779, + "colNumberStop": 9, + "offsetStart": 32450, + "offsetEnd": 32455, + "sourceText": "x \u003d 1;" + } + } + }, + { + "name": "__loc_484", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_495", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 781, + "colNumberStart": 4, + "lineNumberStop": 781, + "colNumberStop": 29, + "offsetStart": 32500, + "offsetEnd": 32525, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "__loc_514", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 784, + "colNumberStart": 4, + "lineNumberStop": 784, + "colNumberStop": 29, + "offsetStart": 32574, + "offsetEnd": 32599, + "sourceText": "__VERIFIER_atomic_begin();" + } + } + }, + { + "name": "thr2_error", + "initial": false, + "final": false, + "error": true, + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + } + } + ], + "edges": [ + { + "source": "thr2_init", + "target": "__loc_290", + "label": { + "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", + "content": {} + }, + "labels": [] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 748, + "colNumberStart": 0, + "lineNumberStop": 788, + "colNumberStop": 29, + "offsetStart": 31581, + "offsetEnd": 32659, + "sourceText": "void *thr2(void *_) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f1 \u003d flag1;\n __VERIFIER_atomic_end();\n while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }\n x \u003d 1;\n if (!(x\u003e\u003d1)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;\n}__VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n int f1 \u003d flag1;\n __VERIFIER_atomic_end();\n while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }\n x \u003d 1;\n if (!(x\u003e\u003d1)) ERROR: reach_error();\n __VERIFIER_atomic_begin();\n turn \u003d 1;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n return 0;__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_191", - "target": "__loc_212", + "source": "__loc_290", + "target": "__loc_309", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1046,13 +2365,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 730, - "colNumberStart": 12, - "lineNumberStop": 730, - "colNumberStop": 36, - "offsetStart": 31175, - "offsetEnd": 31199, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 749, + "colNumberStart": 4, + "lineNumberStop": 749, + "colNumberStop": 29, + "offsetStart": 31607, + "offsetEnd": 31632, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1062,39 +2381,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign flag1 1)" + "content": "(assign flag2 1)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 732, - "colNumberStart": 12, - "lineNumberStop": 732, - "colNumberStop": 34, - "offsetStart": 31237, - "offsetEnd": 31259, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 751, + "colNumberStart": 4, + "lineNumberStop": 751, + "colNumberStop": 27, + "offsetStart": 31653, + "offsetEnd": 31676, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 749, + "colNumberStart": 4, + "lineNumberStop": 752, + "colNumberStop": 29, + "offsetStart": 31607, + "offsetEnd": 31707, + "sourceText": "__VERIFIER_atomic_begin();flag2 \u003d 1;flag2 \u003d 1;flag2 \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_250", - "target": "thr1_error", + "source": "__loc_330", + "target": "__loc_336", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1107,23 +2432,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 739, - "colNumberStart": 8, - "lineNumberStop": 739, - "colNumberStop": 14, - "offsetStart": 31385, - "offsetEnd": 31391, - "sourceText": "!(x\u003c\u003d0)" + "lineNumberStart": 755, + "colNumberStart": 4, + "lineNumberStop": 778, + "colNumberStop": 4, + "offsetStart": 31762, + "offsetEnd": 32444, + "sourceText": "while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (/\u003d (ite (\u003d (ite (\u003c\u003d x 0) 1 0) 0) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003e\u003d thr2::f1 1) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 755, + "colNumberStart": 4, + "lineNumberStop": 778, + "colNumberStop": 33, + "offsetStart": 31762, + "offsetEnd": 32444, + "sourceText": "while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }{\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_282", - "target": "thr1_final", + "source": "__loc_336", + "target": "__loc_357", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1136,13 +2473,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 743, - "colNumberStart": 4, - "lineNumberStop": 743, - "colNumberStop": 28, - "offsetStart": 31494, - "offsetEnd": 31518, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 756, + "colNumberStart": 8, + "lineNumberStop": 756, + "colNumberStop": 33, + "offsetStart": 31788, + "offsetEnd": 31813, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1152,134 +2489,51 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 757, + "colNumberStart": 8, + "lineNumberStop": 757, + "colNumberStop": 20, + "offsetStart": 31823, + "offsetEnd": 31835, + "sourceText": "int t \u003d turn;" } }, - "content": "(assign flag1 0)" + "content": "(assign thr2::while5::t turn)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 745, - "colNumberStart": 4, - "lineNumberStop": 745, - "colNumberStop": 26, - "offsetStart": 31540, - "offsetEnd": 31562, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 758, + "colNumberStart": 8, + "lineNumberStop": 758, + "colNumberStop": 31, + "offsetStart": 31845, + "offsetEnd": 31868, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 746, - "colNumberStart": 4, - "lineNumberStop": 746, - "colNumberStop": 11, - "offsetStart": 31569, - "offsetEnd": 31576, - "sourceText": "return 0" - } - }, - "content": "(assign thr1_ret 0)" } ] - } - } - ] - }, - { - "name": "thr2", - "params": [ - { - "first": { - "type": "hu.bme.mit.theta.core.decl.VarDecl", - "value": { - "name": "thr2_ret", - "type": "Int" - } }, - "second": { - "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", - "value": "OUT" - } - }, - { - "first": { - "type": "hu.bme.mit.theta.core.decl.VarDecl", - "value": { - "name": "thr2::_", - "type": "Int" + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 756, + "colNumberStart": 8, + "lineNumberStop": 774, + "colNumberStop": 33, + "offsetStart": 31788, + "offsetEnd": 32350, + "sourceText": "__VERIFIER_atomic_begin();int t \u003d turn;int t \u003d turn;int t \u003d turn;int t \u003d turn;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }" } - }, - "second": { - "type": "hu.bme.mit.theta.xcfa.model.ParamDirection", - "value": "IN" - } - } - ], - "vars": [ - { - "name": "thr2::f1", - "type": "Int" - }, - { - "name": "thr2::while5::t", - "type": "Int" - }, - { - "name": "thr2_ret", - "type": "Int" - } - ], - "locs": [ - "thr2_init {init}", - "thr2_final {final}", - "__loc_310 ", - "__loc_331 ", - "__loc_352 ", - "__loc_358 ", - "__loc_379 ", - "__loc_385 ", - "__loc_406 ", - "__loc_430 ", - "__loc_436 ", - "__loc_459 ", - "__loc_480 ", - "__loc_506 ", - "__loc_518 ", - "__loc_529 ", - "__loc_550 ", - "thr2_error {error}" - ], - "edges": [ - { - "source": "thr2_init", - "target": "__loc_310", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] } }, { - "source": "__loc_352", - "target": "__loc_358", + "source": "__loc_357", + "target": "__loc_363", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1292,23 +2546,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 755, - "colNumberStart": 11, - "lineNumberStop": 755, - "colNumberStop": 17, - "offsetStart": 31769, - "offsetEnd": 31775, - "sourceText": "f1 \u003e\u003d 1" + "lineNumberStart": 759, + "colNumberStart": 8, + "lineNumberStop": 774, + "colNumberStop": 8, + "offsetStart": 31878, + "offsetEnd": 32350, + "sourceText": "if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (/\u003d (ite (\u003e\u003d thr2::f1 1) 1 0) 0))" + "content": "((assume (/\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 759, + "colNumberStart": 8, + "lineNumberStop": 774, + "colNumberStop": 37, + "offsetStart": 31878, + "offsetEnd": 32350, + "sourceText": "if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }{\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_379", - "target": "__loc_385", + "source": "__loc_363", + "target": "__loc_382", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1317,85 +2583,65 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 759, + "lineNumberStart": 760, "colNumberStart": 12, - "lineNumberStop": 759, - "colNumberStop": 17, - "offsetStart": 31882, - "offsetEnd": 31887, - "sourceText": "t !\u003d 1" + "lineNumberStop": 760, + "colNumberStop": 37, + "offsetStart": 31904, + "offsetEnd": 31929, + "sourceText": "__VERIFIER_atomic_begin();" } }, - "content": "(assume (/\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_430", - "target": "__loc_436", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "F[ATOMIC_BEGIN]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 766, - "colNumberStart": 19, - "lineNumberStop": 766, - "colNumberStop": 24, - "offsetStart": 32108, - "offsetEnd": 32113, - "sourceText": "t !\u003d 1" + "sourceText": "" } }, - "content": "(assume (/\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_430", - "target": "__loc_459", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "(assign flag2 0)" + }, { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 766, + "lineNumberStart": 762, "colNumberStart": 12, - "lineNumberStop": 770, - "colNumberStop": 12, - "offsetStart": 32101, - "offsetEnd": 32240, - "sourceText": "while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" + "lineNumberStop": 762, + "colNumberStop": 35, + "offsetStart": 31966, + "offsetEnd": 31989, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "(assume (\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0))" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 760, + "colNumberStart": 12, + "lineNumberStop": 763, + "colNumberStop": 37, + "offsetStart": 31904, + "offsetEnd": 32028, + "sourceText": "__VERIFIER_atomic_begin();flag2 \u003d 0;flag2 \u003d 0;flag2 \u003d 0;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_379", - "target": "__loc_480", + "source": "__loc_404", + "target": "__loc_410", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1408,52 +2654,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 759, + "lineNumberStart": 766, "colNumberStart": 12, - "lineNumberStop": 759, - "colNumberStop": 17, - "offsetStart": 31882, - "offsetEnd": 31887, - "sourceText": "t !\u003d 1" - } - }, - "content": "(assume (\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0))" - } - ] - } - }, - { - "source": "__loc_352", - "target": "__loc_506", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 755, - "colNumberStart": 4, - "lineNumberStop": 778, - "colNumberStop": 4, - "offsetStart": 31762, - "offsetEnd": 32444, - "sourceText": "while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }" + "lineNumberStop": 770, + "colNumberStop": 12, + "offsetStart": 32101, + "offsetEnd": 32240, + "sourceText": "while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (\u003d (ite (\u003e\u003d thr2::f1 1) 1 0) 0))" + "content": "((assume (/\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 766, + "colNumberStart": 12, + "lineNumberStop": 770, + "colNumberStop": 41, + "offsetStart": 32101, + "offsetEnd": 32240, + "sourceText": "while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }{\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_506", - "target": "__loc_518", + "source": "__loc_404", + "target": "__loc_431", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1466,23 +2695,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 766, + "colNumberStart": 12, + "lineNumberStop": 770, + "colNumberStop": 12, + "offsetStart": 32101, + "offsetEnd": 32240, + "sourceText": "while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assign x 1)" + "content": "((assume (\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 766, + "colNumberStart": 12, + "lineNumberStop": 771, + "colNumberStop": 37, + "offsetStart": 32101, + "offsetEnd": 32280, + "sourceText": "while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_518", - "target": "__loc_529", + "source": "__loc_330", + "target": "__loc_472", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1495,23 +2736,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 780, - "colNumberStart": 8, - "lineNumberStop": 780, - "colNumberStop": 14, - "offsetStart": 32465, - "offsetEnd": 32471, - "sourceText": "!(x\u003e\u003d1)" + "lineNumberStart": 755, + "colNumberStart": 4, + "lineNumberStop": 778, + "colNumberStop": 4, + "offsetStart": 31762, + "offsetEnd": 32444, + "sourceText": "while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }" } }, - "content": "(assume (\u003d (ite (\u003d (ite (\u003e\u003d x 1) 1 0) 0) 1 0) 0))" + "content": "((assume (\u003d (ite (\u003e\u003d thr2::f1 1) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 755, + "colNumberStart": 4, + "lineNumberStop": 779, + "colNumberStop": 9, + "offsetStart": 31762, + "offsetEnd": 32455, + "sourceText": "while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }x \u003d 1;x \u003d 1;x \u003d 1;" + } } }, { - "source": "__loc_310", - "target": "__loc_331", + "source": "__loc_472", + "target": "__loc_484", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1519,60 +2772,34 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 749, - "colNumberStart": 4, - "lineNumberStop": 749, - "colNumberStop": 28, - "offsetStart": 31607, - "offsetEnd": 31631, - "sourceText": "__VERIFIER_atomic_begin()" - } - }, - "content": "F[ATOMIC_BEGIN]" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign flag2 1)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 751, - "colNumberStart": 4, - "lineNumberStop": 751, - "colNumberStop": 26, - "offsetStart": 31653, - "offsetEnd": 31675, - "sourceText": "__VERIFIER_atomic_end()" - } - }, - "content": "F[ATOMIC_END]" + "content": "(assign x 1)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 0, + "colNumberStart": 0, + "lineNumberStop": 780, + "colNumberStop": 37, + "offsetStart": 0, + "offsetEnd": 32494, + "sourceText": "if (!(x\u003e\u003d1)) ERROR: reach_error();if (!(x\u003e\u003d1)) ERROR: reach_error();if (!(x\u003e\u003d1)) ERROR: reach_error();if (!(x\u003e\u003d1)) ERROR: reach_error();if (!(x\u003e\u003d1)) ERROR: reach_error();" + } } }, { - "source": "__loc_331", - "target": "__loc_352", + "source": "__loc_484", + "target": "thr2_error", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1580,60 +2807,40 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 752, - "colNumberStart": 4, - "lineNumberStop": 752, - "colNumberStop": 28, - "offsetStart": 31682, - "offsetEnd": 31706, - "sourceText": "__VERIFIER_atomic_begin()" - } - }, - "content": "F[ATOMIC_BEGIN]" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 753, - "colNumberStart": 4, - "lineNumberStop": 753, - "colNumberStop": 18, - "offsetStart": 31713, - "offsetEnd": 31727, - "sourceText": "int f1 \u003d flag1;" - } - }, - "content": "(assign thr2::f1 flag1)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 754, + "lineNumberStart": 780, "colNumberStart": 4, - "lineNumberStop": 754, - "colNumberStop": 26, - "offsetStart": 31733, - "offsetEnd": 31755, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStop": 780, + "colNumberStop": 37, + "offsetStart": 32461, + "offsetEnd": 32494, + "sourceText": "if (!(x\u003e\u003d1)) ERROR: reach_error();" } }, - "content": "F[ATOMIC_END]" + "content": "((assume (/\u003d (ite (\u003d (ite (\u003e\u003d x 1) 1 0) 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 780, + "colNumberStart": 4, + "lineNumberStop": 780, + "colNumberStop": 37, + "offsetStart": 32461, + "offsetEnd": 32494, + "sourceText": "if (!(x\u003e\u003d1)) ERROR: reach_error();ERROR: reach_error();reach_error();reach_error();reach_error();reach_error();" + } } }, { - "source": "__loc_358", - "target": "__loc_379", + "source": "__loc_484", + "target": "__loc_495", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1641,60 +2848,40 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 756, - "colNumberStart": 8, - "lineNumberStop": 756, - "colNumberStop": 32, - "offsetStart": 31788, - "offsetEnd": 31812, - "sourceText": "__VERIFIER_atomic_begin()" - } - }, - "content": "F[ATOMIC_BEGIN]" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 757, - "colNumberStart": 8, - "lineNumberStop": 757, - "colNumberStop": 20, - "offsetStart": 31823, - "offsetEnd": 31835, - "sourceText": "int t \u003d turn;" - } - }, - "content": "(assign thr2::while5::t turn)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 758, - "colNumberStart": 8, - "lineNumberStop": 758, - "colNumberStop": 30, - "offsetStart": 31845, - "offsetEnd": 31867, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 780, + "colNumberStart": 4, + "lineNumberStop": 780, + "colNumberStop": 37, + "offsetStart": 32461, + "offsetEnd": 32494, + "sourceText": "if (!(x\u003e\u003d1)) ERROR: reach_error();" } }, - "content": "F[ATOMIC_END]" + "content": "((assume (\u003d (ite (\u003d (ite (\u003e\u003d x 1) 1 0) 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 780, + "colNumberStart": 4, + "lineNumberStop": 781, + "colNumberStop": 37, + "offsetStart": 32461, + "offsetEnd": 32525, + "sourceText": "if (!(x\u003e\u003d1)) ERROR: reach_error();if (!(x\u003e\u003d1)) ERROR: reach_error();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_529", - "target": "__loc_550", + "source": "__loc_495", + "target": "__loc_514", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1710,10 +2897,10 @@ "lineNumberStart": 781, "colNumberStart": 4, "lineNumberStop": 781, - "colNumberStop": 28, + "colNumberStop": 29, "offsetStart": 32500, - "offsetEnd": 32524, - "sourceText": "__VERIFIER_atomic_begin()" + "offsetEnd": 32525, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1723,12 +2910,6 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -1742,20 +2923,32 @@ "lineNumberStart": 783, "colNumberStart": 4, "lineNumberStop": 783, - "colNumberStop": 26, + "colNumberStop": 27, "offsetStart": 32545, - "offsetEnd": 32567, - "sourceText": "__VERIFIER_atomic_end()" + "offsetEnd": 32568, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 781, + "colNumberStart": 4, + "lineNumberStop": 784, + "colNumberStop": 29, + "offsetStart": 32500, + "offsetEnd": 32599, + "sourceText": "__VERIFIER_atomic_begin();turn \u003d 1;turn \u003d 1;turn \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_385", - "target": "__loc_406", + "source": "__loc_514", + "target": "thr2_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1768,13 +2961,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 760, - "colNumberStart": 12, - "lineNumberStop": 760, - "colNumberStop": 36, - "offsetStart": 31904, - "offsetEnd": 31928, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 784, + "colNumberStart": 4, + "lineNumberStop": 784, + "colNumberStop": 29, + "offsetStart": 32574, + "offsetEnd": 32599, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1784,12 +2977,6 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -1800,23 +2987,51 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 762, - "colNumberStart": 12, - "lineNumberStop": 762, - "colNumberStop": 34, - "offsetStart": 31966, - "offsetEnd": 31988, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 786, + "colNumberStart": 4, + "lineNumberStop": 786, + "colNumberStop": 27, + "offsetStart": 32620, + "offsetEnd": 32643, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 787, + "colNumberStart": 4, + "lineNumberStop": 787, + "colNumberStop": 12, + "offsetStart": 32649, + "offsetEnd": 32657, + "sourceText": "return 0;" + } + }, + "content": "(assign thr2_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 784, + "colNumberStart": 4, + "lineNumberStop": 787, + "colNumberStop": 29, + "offsetStart": 32574, + "offsetEnd": 32657, + "sourceText": "__VERIFIER_atomic_begin();flag2 \u003d 0;flag2 \u003d 0;flag2 \u003d 0;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();return 0;return 0;return 0;return 0;" + } } }, { - "source": "__loc_480", - "target": "__loc_352", + "source": "__loc_309", + "target": "__loc_330", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1829,13 +3044,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 775, - "colNumberStart": 8, - "lineNumberStop": 775, - "colNumberStop": 32, - "offsetStart": 32360, - "offsetEnd": 32384, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 752, + "colNumberStart": 4, + "lineNumberStop": 752, + "colNumberStop": 29, + "offsetStart": 31682, + "offsetEnd": 31707, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1845,13 +3060,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" + "lineNumberStart": 753, + "colNumberStart": 4, + "lineNumberStop": 753, + "colNumberStop": 18, + "offsetStart": 31713, + "offsetEnd": 31727, + "sourceText": "int f1 \u003d flag1;" } }, "content": "(assign thr2::f1 flag1)" @@ -1861,23 +3076,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 777, - "colNumberStart": 8, - "lineNumberStop": 777, - "colNumberStop": 30, - "offsetStart": 32415, - "offsetEnd": 32437, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 754, + "colNumberStart": 4, + "lineNumberStop": 754, + "colNumberStop": 27, + "offsetStart": 31733, + "offsetEnd": 31756, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 752, + "colNumberStart": 4, + "lineNumberStop": 778, + "colNumberStop": 29, + "offsetStart": 31682, + "offsetEnd": 32444, + "sourceText": "__VERIFIER_atomic_begin();int f1 \u003d flag1;int f1 \u003d flag1;int f1 \u003d flag1;int f1 \u003d flag1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_406", - "target": "__loc_430", + "source": "__loc_450", + "target": "__loc_330", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1890,13 +3117,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 763, - "colNumberStart": 12, - "lineNumberStop": 763, - "colNumberStop": 36, - "offsetStart": 32003, - "offsetEnd": 32027, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 775, + "colNumberStart": 8, + "lineNumberStop": 775, + "colNumberStop": 33, + "offsetStart": 32360, + "offsetEnd": 32385, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -1906,39 +3133,45 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign thr2::while5::t turn)" + "content": "(assign thr2::f1 flag1)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 765, - "colNumberStart": 12, - "lineNumberStop": 765, - "colNumberStop": 34, - "offsetStart": 32064, - "offsetEnd": 32086, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 777, + "colNumberStart": 8, + "lineNumberStop": 777, + "colNumberStop": 31, + "offsetStart": 32415, + "offsetEnd": 32438, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 755, + "colNumberStart": 4, + "lineNumberStop": 778, + "colNumberStop": 33, + "offsetStart": 31762, + "offsetEnd": 32444, + "sourceText": "__VERIFIER_atomic_begin();f1 \u003d flag1;f1 \u003d flag1;f1 \u003d flag1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }while (f1 \u003e\u003d 1) {\n __VERIFIER_atomic_begin();\n int t \u003d turn;\n __VERIFIER_atomic_end();\n if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }\n __VERIFIER_atomic_begin();\n f1 \u003d flag1;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_436", - "target": "__loc_430", + "source": "__loc_357", + "target": "__loc_450", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -1946,60 +3179,40 @@ "content": {} }, "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 767, - "colNumberStart": 16, - "lineNumberStop": 767, - "colNumberStop": 40, - "offsetStart": 32134, - "offsetEnd": 32158, - "sourceText": "__VERIFIER_atomic_begin()" - } - }, - "content": "F[ATOMIC_BEGIN]" - }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, - "sourceText": "" - } - }, - "content": "(assign thr2::while5::t turn)" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 769, - "colNumberStart": 16, - "lineNumberStop": 769, - "colNumberStop": 38, - "offsetStart": 32203, - "offsetEnd": 32225, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 759, + "colNumberStart": 8, + "lineNumberStop": 774, + "colNumberStop": 8, + "offsetStart": 31878, + "offsetEnd": 32350, + "sourceText": "if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }" } }, - "content": "F[ATOMIC_END]" + "content": "((assume (\u003d (ite (/\u003d thr2::while5::t 1) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 759, + "colNumberStart": 8, + "lineNumberStop": 775, + "colNumberStop": 33, + "offsetStart": 31878, + "offsetEnd": 32385, + "sourceText": "if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_459", - "target": "__loc_480", + "source": "__loc_431", + "target": "__loc_450", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2015,10 +3228,10 @@ "lineNumberStart": 771, "colNumberStart": 12, "lineNumberStop": 771, - "colNumberStop": 36, + "colNumberStop": 37, "offsetStart": 32255, - "offsetEnd": 32279, - "sourceText": "__VERIFIER_atomic_begin()" + "offsetEnd": 32280, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -2028,12 +3241,6 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, @@ -2047,20 +3254,32 @@ "lineNumberStart": 773, "colNumberStart": 12, "lineNumberStop": 773, - "colNumberStop": 34, + "colNumberStop": 35, "offsetStart": 32317, - "offsetEnd": 32339, - "sourceText": "__VERIFIER_atomic_end()" + "offsetEnd": 32340, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 759, + "colNumberStart": 8, + "lineNumberStop": 775, + "colNumberStop": 37, + "offsetStart": 31878, + "offsetEnd": 32385, + "sourceText": "__VERIFIER_atomic_begin();flag2 \u003d 1;flag2 \u003d 1;flag2 \u003d 1;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();if (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n flag2 \u003d 0;\n __VERIFIER_atomic_end();\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n };\n __VERIFIER_atomic_begin();\n flag2 \u003d 1;\n __VERIFIER_atomic_end();\n }__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();__VERIFIER_atomic_begin();" + } } }, { - "source": "__loc_518", - "target": "thr2_error", + "source": "__loc_382", + "target": "__loc_404", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2069,27 +3288,65 @@ }, "labels": [ { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 763, + "colNumberStart": 12, + "lineNumberStop": 763, + "colNumberStop": 37, + "offsetStart": 32003, + "offsetEnd": 32028, + "sourceText": "__VERIFIER_atomic_begin();" + } + }, + "content": "F[ATOMIC_BEGIN]" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + }, + "content": "(assign thr2::while5::t turn)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 780, - "colNumberStart": 8, - "lineNumberStop": 780, - "colNumberStop": 14, - "offsetStart": 32465, - "offsetEnd": 32471, - "sourceText": "!(x\u003e\u003d1)" + "lineNumberStart": 765, + "colNumberStart": 12, + "lineNumberStop": 765, + "colNumberStop": 35, + "offsetStart": 32064, + "offsetEnd": 32087, + "sourceText": "__VERIFIER_atomic_end();" } }, - "content": "(assume (/\u003d (ite (\u003d (ite (\u003e\u003d x 1) 1 0) 0) 1 0) 0))" + "content": "F[ATOMIC_END]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 763, + "colNumberStart": 12, + "lineNumberStop": 770, + "colNumberStop": 37, + "offsetStart": 32003, + "offsetEnd": 32240, + "sourceText": "__VERIFIER_atomic_begin();t \u003d turn;t \u003d turn;t \u003d turn;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" + } } }, { - "source": "__loc_550", - "target": "thr2_final", + "source": "__loc_410", + "target": "__loc_404", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2102,13 +3359,13 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 784, - "colNumberStart": 4, - "lineNumberStop": 784, - "colNumberStop": 28, - "offsetStart": 32574, - "offsetEnd": 32598, - "sourceText": "__VERIFIER_atomic_begin()" + "lineNumberStart": 767, + "colNumberStart": 16, + "lineNumberStop": 767, + "colNumberStop": 41, + "offsetStart": 32134, + "offsetEnd": 32159, + "sourceText": "__VERIFIER_atomic_begin();" } }, "content": "F[ATOMIC_BEGIN]" @@ -2118,50 +3375,40 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assign flag2 0)" + "content": "(assign thr2::while5::t turn)" }, { "type": "hu.bme.mit.theta.xcfa.model.FenceLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 786, - "colNumberStart": 4, - "lineNumberStop": 786, - "colNumberStop": 26, - "offsetStart": 32620, - "offsetEnd": 32642, - "sourceText": "__VERIFIER_atomic_end()" + "lineNumberStart": 769, + "colNumberStart": 16, + "lineNumberStop": 769, + "colNumberStop": 39, + "offsetStart": 32203, + "offsetEnd": 32226, + "sourceText": "__VERIFIER_atomic_end();" } }, "content": "F[ATOMIC_END]" - }, - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 787, - "colNumberStart": 4, - "lineNumberStop": 787, - "colNumberStop": 11, - "offsetStart": 32649, - "offsetEnd": 32656, - "sourceText": "return 0" - } - }, - "content": "(assign thr2_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 766, + "colNumberStart": 12, + "lineNumberStop": 770, + "colNumberStop": 41, + "offsetStart": 32101, + "offsetEnd": 32240, + "sourceText": "__VERIFIER_atomic_begin();t \u003d turn;t \u003d turn;t \u003d turn;__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();__VERIFIER_atomic_end();while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }while (t !\u003d 1) {\n __VERIFIER_atomic_begin();\n t \u003d turn;\n __VERIFIER_atomic_end();\n }" + } } } ] @@ -2184,6 +3431,10 @@ } ], "vars": [ + { + "name": "main_ret", + "type": "Int" + }, { "name": "main::t1", "type": "Int" @@ -2193,72 +3444,170 @@ "type": "Int" }, { - "name": "main_ret", + "name": "call_assume_abort_if_not_ret43", "type": "Int" }, { - "name": "call_assume_abort_if_not_ret43", + "name": "call_pthread_create_ret44", "type": "Int" }, { - "name": "assume_abort_if_not::cond", + "name": "call_pthread_create_ret45", + "type": "Int" + }, + { + "name": "call_pthread_join_ret46", + "type": "Int" + }, + { + "name": "call_pthread_join_ret47", "type": "Int" }, { "name": "assume_abort_if_not_ret", "type": "Int" + }, + { + "name": "assume_abort_if_not::cond", + "type": "Int" + }, + { + "name": "call_abort_ret0", + "type": "Int" } ], "locs": [ - "main_init {init}", - "main_final {final}", - "__loc_577 ", - "__loc_579 ", - "__loc_588 ", - "__loc_606 ", - "__loc_624 ", - "__loc_636 ", - "__loc_648 ", - "__loc_654 ", - "__loc_2658 ", - "assume_abort_if_not_final657 ", - "assume_abort_if_not_init656 ", - "__loc_7659 ", - "__loc_13660 " - ], - "edges": [ { - "source": "__loc_654", - "target": "main_final", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ - { - "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", - "metadata": { - "type": "hu.bme.mit.theta.c2xcfa.CMetaData", - "content": { - "lineNumberStart": 796, - "colNumberStart": 2, - "lineNumberStop": 796, - "colNumberStop": 9, - "offsetStart": 32855, - "offsetEnd": 32862, - "sourceText": "return 0" - } - }, - "content": "(assign main_ret 0)" - } - ] + "name": "main_init", + "initial": true, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 789, + "colNumberStart": 0, + "lineNumberStop": 797, + "colNumberStop": 0, + "offsetStart": 32661, + "offsetEnd": 32865, + "sourceText": "int main() {\n pthread_t t1, t2;\n assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n return 0;\n}" + } + } + }, + { + "name": "main_final", + "initial": false, + "final": true, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 789, + "colNumberStart": 0, + "lineNumberStop": 797, + "colNumberStop": 0, + "offsetStart": 32661, + "offsetEnd": 32865, + "sourceText": "int main() {\n pthread_t t1, t2;\n assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n return 0;\n}" + } + } + }, + { + "name": "__loc_550", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_568", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_586", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_598", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_610", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } + } + }, + { + "name": "__loc_8_628", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "sourceText": "" + } } }, + { + "name": "__loc_14_634", + "initial": false, + "final": false, + "error": false, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 13, + "lineNumberStop": 3, + "colNumberStop": 20, + "offsetStart": 75, + "offsetEnd": 82, + "sourceText": "abort();" + } + } + } + ], + "edges": [ { "source": "main_init", - "target": "__loc_577", + "target": "__loc_550", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2297,71 +3646,45 @@ "content": {} }, "content": "(assign x 0)" - } - ] - } - }, - { - "source": "__loc_577", - "target": "__loc_579", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::t1 0) (\u003c\u003d main::t1 4294967295)))" - } - ] - } - }, - { - "source": "__loc_579", - "target": "__loc_588", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + "content": "((assume (and (\u003e\u003d main::t1 0) (\u003c\u003d main::t1 18446744073709551615))))[choiceType\u003dMAIN_PATH]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": -1, - "colNumberStart": -1, - "lineNumberStop": -1, - "colNumberStop": -1, - "offsetStart": -1, - "offsetEnd": -1, "sourceText": "" } }, - "content": "(assume (and (\u003e\u003d main::t2 0) (\u003c\u003d main::t2 4294967295)))" + "content": "((assume (and (\u003e\u003d main::t2 0) (\u003c\u003d main::t2 18446744073709551615))))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 789, + "colNumberStart": 0, + "lineNumberStop": 797, + "colNumberStop": 41, + "offsetStart": 32661, + "offsetEnd": 32865, + "sourceText": "int main() {\n pthread_t t1, t2;\n assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n return 0;\n}pthread_t t1, t2;\n assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);\n pthread_create(\u0026t1, 0, thr1, 0);\n pthread_create(\u0026t2, 0, thr2, 0);\n pthread_join(t1, 0);\n pthread_join(t2, 0);\n return 0;pthread_t t1, t2;assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);" + } } }, { - "source": "__loc_606", - "target": "__loc_624", + "source": "__loc_568", + "target": "__loc_586", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2377,20 +3700,32 @@ "lineNumberStart": 792, "colNumberStart": 2, "lineNumberStop": 792, - "colNumberStop": 32, + "colNumberStop": 33, "offsetStart": 32739, - "offsetEnd": 32769, - "sourceText": "pthread_create(\u0026t1, 0, thr1, 0)" + "offsetEnd": 32770, + "sourceText": "pthread_create(\u0026t1, 0, thr1, 0);" } }, - "content": "(var main::t1 Int) \u003d start thr1(0)" + "content": "(var main::t1 Int) \u003d start thr1(0, 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 792, + "colNumberStart": 2, + "lineNumberStop": 793, + "colNumberStop": 33, + "offsetStart": 32739, + "offsetEnd": 32805, + "sourceText": "pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);pthread_create(\u0026t2, 0, thr2, 0);" + } } }, { - "source": "__loc_624", - "target": "__loc_636", + "source": "__loc_586", + "target": "__loc_598", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2406,20 +3741,32 @@ "lineNumberStart": 793, "colNumberStart": 2, "lineNumberStop": 793, - "colNumberStop": 32, + "colNumberStop": 33, "offsetStart": 32774, - "offsetEnd": 32804, - "sourceText": "pthread_create(\u0026t2, 0, thr2, 0)" + "offsetEnd": 32805, + "sourceText": "pthread_create(\u0026t2, 0, thr2, 0);" } }, - "content": "(var main::t2 Int) \u003d start thr2(0)" + "content": "(var main::t2 Int) \u003d start thr2(0, 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 793, + "colNumberStart": 2, + "lineNumberStop": 794, + "colNumberStop": 33, + "offsetStart": 32774, + "offsetEnd": 32828, + "sourceText": "pthread_create(\u0026t2, 0, thr2, 0);pthread_join(t1, 0);pthread_join(t1, 0);pthread_join(t1, 0);pthread_join(t1, 0);pthread_join(t1, 0);" + } } }, { - "source": "__loc_636", - "target": "__loc_648", + "source": "__loc_598", + "target": "__loc_610", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2435,20 +3782,32 @@ "lineNumberStart": 794, "colNumberStart": 2, "lineNumberStop": 794, - "colNumberStop": 20, + "colNumberStop": 21, "offsetStart": 32809, - "offsetEnd": 32827, - "sourceText": "pthread_join(t1, 0)" + "offsetEnd": 32828, + "sourceText": "pthread_join(t1, 0);" } }, "content": "join (var main::t1 Int)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 794, + "colNumberStart": 2, + "lineNumberStop": 795, + "colNumberStop": 21, + "offsetStart": 32809, + "offsetEnd": 32851, + "sourceText": "pthread_join(t1, 0);pthread_join(t2, 0);pthread_join(t2, 0);pthread_join(t2, 0);pthread_join(t2, 0);pthread_join(t2, 0);" + } } }, { - "source": "__loc_648", - "target": "__loc_654", + "source": "__loc_610", + "target": "main_final", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2464,44 +3823,48 @@ "lineNumberStart": 795, "colNumberStart": 2, "lineNumberStop": 795, - "colNumberStop": 20, + "colNumberStop": 21, "offsetStart": 32832, - "offsetEnd": 32850, - "sourceText": "pthread_join(t2, 0)" + "offsetEnd": 32851, + "sourceText": "pthread_join(t2, 0);" } }, "content": "join (var main::t2 Int)" + }, + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 796, + "colNumberStart": 2, + "lineNumberStop": 796, + "colNumberStop": 10, + "offsetStart": 32855, + "offsetEnd": 32863, + "sourceText": "return 0;" + } + }, + "content": "(assign main_ret 0)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 795, + "colNumberStart": 2, + "lineNumberStop": 796, + "colNumberStop": 21, + "offsetStart": 32832, + "offsetEnd": 32863, + "sourceText": "pthread_join(t2, 0);return 0;return 0;return 0;return 0;" + } } }, { - "source": "__loc_2658", - "target": "assume_abort_if_not_final657", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] - } - }, - { - "source": "assume_abort_if_not_init656", - "target": "__loc_7659", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [] - } - }, - { - "source": "__loc_7659", - "target": "__loc_13660", + "source": "__loc_550", + "target": "__loc_8_628", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2514,23 +3877,35 @@ "metadata": { "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { - "lineNumberStart": 3, - "colNumberStart": 5, - "lineNumberStop": 3, - "colNumberStop": 9, - "offsetStart": 67, - "offsetEnd": 71, - "sourceText": "!cond" + "lineNumberStart": 791, + "colNumberStart": 2, + "lineNumberStop": 791, + "colNumberStop": 41, + "offsetStart": 32696, + "offsetEnd": 32735, + "sourceText": "assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);" } }, - "content": "(assume (/\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0))" + "content": "(assign assume_abort_if_not::cond (ite (and (/\u003d 0 (ite (\u003c\u003d 0 turn) 1 0)) (/\u003d 0 (ite (\u003c\u003d turn 1) 1 0))) 1 0))" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 791, + "colNumberStop": 41, + "offsetStart": 25, + "offsetEnd": 32735, + "sourceText": "assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);void assume_abort_if_not(int cond) {\n if(!cond) {abort();}\n}if(!cond) {abort();}if(!cond) {abort();}if(!cond) {abort();}if(!cond) {abort();}" + } } }, { - "source": "__loc_7659", - "target": "__loc_2658", + "source": "__loc_8_628", + "target": "__loc_14_634", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2544,22 +3919,34 @@ "type": "hu.bme.mit.theta.c2xcfa.CMetaData", "content": { "lineNumberStart": 3, - "colNumberStart": 5, + "colNumberStart": 2, "lineNumberStop": 3, - "colNumberStop": 9, - "offsetStart": 67, - "offsetEnd": 71, - "sourceText": "!cond" + "colNumberStop": 21, + "offsetStart": 64, + "offsetEnd": 83, + "sourceText": "if(!cond) {abort();}" } }, - "content": "(assume (\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0))" + "content": "((assume (/\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0)))[choiceType\u003dMAIN_PATH]" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 2, + "lineNumberStop": 3, + "colNumberStop": 21, + "offsetStart": 64, + "offsetEnd": 83, + "sourceText": "if(!cond) {abort();}{abort();}abort();abort();abort();" + } } }, { - "source": "__loc_13660", - "target": "assume_abort_if_not_final657", + "source": "__loc_14_634", + "target": "__loc_568", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2570,24 +3957,19 @@ { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 13, + "lineNumberStop": 3, + "colNumberStop": 20, + "offsetStart": 75, + "offsetEnd": 82, + "sourceText": "abort();" + } }, "content": "(assume false)" - } - ] - } - }, - { - "source": "__loc_588", - "target": "assume_abort_if_not_init656", - "label": { - "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", - "metadata": { - "type": "hu.bme.mit.theta.xcfa.model.EmptyMetaData", - "content": {} - }, - "labels": [ + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2596,20 +3978,32 @@ "lineNumberStart": 791, "colNumberStart": 2, "lineNumberStop": 791, - "colNumberStop": 40, + "colNumberStop": 41, "offsetStart": 32696, - "offsetEnd": 32734, - "sourceText": "assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1)" + "offsetEnd": 32735, + "sourceText": "assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);" } }, - "content": "(assign assume_abort_if_not::cond (+ (ite (and (/\u003d 0 (ite (\u003c\u003d (+ 0) (+ turn)) 1 0)) (/\u003d 0 (ite (\u003c\u003d (+ turn) (+ 1)) 1 0))) 1 0)))" + "content": "(assign call_assume_abort_if_not_ret43 assume_abort_if_not_ret)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 2, + "lineNumberStop": 792, + "colNumberStop": 33, + "offsetStart": 75, + "offsetEnd": 32770, + "sourceText": "abort();pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);" + } } }, { - "source": "assume_abort_if_not_final657", - "target": "__loc_606", + "source": "__loc_8_628", + "target": "__loc_568", "label": { "type": "hu.bme.mit.theta.xcfa.model.SequenceLabel", "metadata": { @@ -2617,6 +4011,22 @@ "content": {} }, "labels": [ + { + "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 3, + "colNumberStart": 2, + "lineNumberStop": 3, + "colNumberStop": 21, + "offsetStart": 64, + "offsetEnd": 83, + "sourceText": "if(!cond) {abort();}" + } + }, + "content": "((assume (\u003d (ite (\u003d assume_abort_if_not::cond 0) 1 0) 0)))[choiceType\u003dALTERNATIVE_PATH]" + }, { "type": "hu.bme.mit.theta.xcfa.model.StmtLabel", "metadata": { @@ -2625,15 +4035,27 @@ "lineNumberStart": 791, "colNumberStart": 2, "lineNumberStop": 791, - "colNumberStop": 40, + "colNumberStop": 41, "offsetStart": 32696, - "offsetEnd": 32734, - "sourceText": "assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1)" + "offsetEnd": 32735, + "sourceText": "assume_abort_if_not(0\u003c\u003dturn \u0026\u0026 turn\u003c\u003d1);" } }, "content": "(assign call_assume_abort_if_not_ret43 assume_abort_if_not_ret)" } ] + }, + "metadata": { + "type": "hu.bme.mit.theta.c2xcfa.CMetaData", + "content": { + "lineNumberStart": 2, + "colNumberStart": 0, + "lineNumberStop": 792, + "colNumberStop": 33, + "offsetStart": 25, + "offsetEnd": 32770, + "sourceText": "if(!cond) {abort();}if(!cond) {abort();}void assume_abort_if_not(int cond) {\n if(!cond) {abort();}\n}pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);pthread_create(\u0026t1, 0, thr1, 0);" + } } } ] diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt index 9cf2736445..f4a5801ad3 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt @@ -57,6 +57,8 @@ class XcfaAdapter(val gsonSupplier: () -> Gson) : TypeAdapter() { .name("target").value(it.target.name) .name("label") gson.toJson(gson.toJsonTree(it.label), writer) + writer.name("metadata") + gson.toJson(gson.toJsonTree(it.metadata), writer) writer.endObject() } }.endArray() @@ -139,6 +141,7 @@ class XcfaAdapter(val gsonSupplier: () -> Gson) : TypeAdapter() { val varsType = object : TypeToken>>() {}.type val locsType = object : TypeToken>() {}.type val labelType = object : TypeToken() {}.type + val metadataType = object : TypeToken() {}.type while (reader.peek() != JsonToken.END_ARRAY) { reader.beginObject() @@ -173,14 +176,16 @@ class XcfaAdapter(val gsonSupplier: () -> Gson) : TypeAdapter() { lateinit var source: XcfaLocation lateinit var target: XcfaLocation lateinit var label: XcfaLabel + lateinit var metadata: MetaData while (reader.peek() != JsonToken.END_OBJECT) { when (reader.nextName()) { "source" -> source = checkNotNull(locs[reader.nextString()]) "target" -> target = checkNotNull(locs[reader.nextString()]) "label" -> label = gson.fromJson(reader, labelType) + "metadata" -> metadata = gson.fromJson(reader, metadataType) } } - val edge = XcfaEdge(source, target, label) + val edge = XcfaEdge(source, target, label, metadata) edges.add(edge) source.outgoingEdges.add(edge) target.incomingEdges.add(edge) diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt index 77d7743c64..02d6e50e50 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt @@ -16,11 +16,57 @@ package hu.bme.mit.theta.xcfa.gson +import com.google.gson.Gson +import com.google.gson.TypeAdapter +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonWriter +import hu.bme.mit.theta.xcfa.model.EmptyMetaData +import hu.bme.mit.theta.xcfa.model.MetaData import hu.bme.mit.theta.xcfa.model.XcfaLocation -val xcfaLocationAdapter: (String) -> XcfaLocation = { - val matchResult = Regex("^([^{ }]*) (\\{.*})?$").matchEntire(it) - check(matchResult != null) - val (name, modifier) = matchResult.destructured - XcfaLocation(name, modifier == "{init}", modifier == "{final}", modifier == "{error}") +class XcfaLocationAdapter(val gsonSupplier: () -> Gson) : TypeAdapter() { + + private lateinit var gson: Gson + override fun write(writer: JsonWriter, value: XcfaLocation) { + initGson() + writer.beginObject() + writer.name("name").value(value.name) + writer.name("initial").value(value.initial) + writer.name("final").value(value.final) + writer.name("error").value(value.error) + writer.name("metadata") + gson.toJson(gson.toJsonTree(value.metadata), writer) + writer.endObject() + } + + override fun read(reader: JsonReader): XcfaLocation { + initGson() + reader.beginObject() + + lateinit var name: String + var initial = false + var final = false + var error = false + var metaData: MetaData? = null + + while (reader.hasNext()) { + val jsonName = reader.nextName() + when (jsonName) { + "name" -> name = reader.nextString() + "initial" -> initial = reader.nextBoolean() + "final" -> final = reader.nextBoolean() + "error" -> error = reader.nextBoolean() + "metaData" -> metaData = gson.fromJson(reader, MetaData::class.java) + else -> reader.skipValue() + } + } + reader.endObject() + + return XcfaLocation(name, initial, final, error, metaData ?: EmptyMetaData) + } + + private fun initGson() { + if (!this::gson.isInitialized) gson = gsonSupplier() + } + } \ No newline at end of file diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt index b146c7d4f9..96b21e4b97 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt @@ -275,14 +275,14 @@ class XcfaProcedureBuilderContext(val builder: XcfaProcedureBuilder) { } infix fun String.to(to: String): (lambda: SequenceLabelContext.() -> SequenceLabel) -> XcfaEdge { - val loc1 = locationLut.getOrElse(this) { XcfaLocation(this) } + val loc1 = locationLut.getOrElse(this) { XcfaLocation(this, metadata = EmptyMetaData) } locationLut.putIfAbsent(this, loc1) builder.addLoc(loc1) - val loc2 = locationLut.getOrElse(to) { XcfaLocation(to) } + val loc2 = locationLut.getOrElse(to) { XcfaLocation(to, metadata = EmptyMetaData) } locationLut.putIfAbsent(to, loc2) builder.addLoc(loc2) return { lambda -> - val edge = XcfaEdge(loc1, loc2, lambda(SequenceLabelContext())) + val edge = XcfaEdge(loc1, loc2, lambda(SequenceLabelContext()), EmptyMetaData) builder.addEdge(edge) edge } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt index c47200a0d6..ea1afc35ac 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt @@ -16,13 +16,19 @@ package hu.bme.mit.theta.xcfa.model -abstract class MetaData +abstract class MetaData { + + abstract fun combine(other: MetaData): MetaData +} object EmptyMetaData : MetaData() { // TODO why is this necessary? {@see GsonTest.kt} - private val hash = 123123 + override fun combine(other: MetaData): MetaData { + return other + } + override fun equals(other: Any?): Boolean = other is EmptyMetaData diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt index 0c5c4c461d..0248095a83 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt @@ -26,14 +26,14 @@ class EliminateSelfLoops : ProcedurePass { for (selfLoop in selfLoops) { builder.removeEdge(selfLoop) val source = selfLoop.source - val target = XcfaLocation(source.name + "_" + XcfaLocation.uniqueCounter()) + val target = XcfaLocation(source.name + "_" + XcfaLocation.uniqueCounter(), metadata = EmptyMetaData) builder.addLoc(target) for (outgoingEdge in LinkedHashSet(source.outgoingEdges)) { builder.removeEdge(outgoingEdge) - builder.addEdge(XcfaEdge(target, outgoingEdge.target, outgoingEdge.label)) + builder.addEdge(XcfaEdge(target, outgoingEdge.target, outgoingEdge.label, outgoingEdge.metadata)) } - builder.addEdge(XcfaEdge(source, target, selfLoop.label)) - builder.addEdge(XcfaEdge(target, source, SequenceLabel(listOf(NopLabel)))) + builder.addEdge(XcfaEdge(source, target, selfLoop.label, selfLoop.metadata)) + builder.addEdge(XcfaEdge(target, source, SequenceLabel(listOf(NopLabel)), selfLoop.metadata)) } builder.metaData["noSelfLoops"] = Unit return builder diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt index 987722b622..3effbf99a7 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt @@ -39,7 +39,10 @@ class FinalLocationPass(private val checkOverflow: Boolean) : ProcedurePass { builder.addEdge(XcfaEdge(it.source, builder.finalLoc.get(), SequenceLabel( listOf( StmtLabel(Stmts.Assume(BoolExprs.False()), metadata = it.metadata)), - metadata = it.metadata))) + metadata = it.metadata + ), it.metadata + ) + ) } else { builder.addEdge(it) } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt index 8a05f0ef2b..fb8f0d4b31 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt @@ -50,7 +50,7 @@ class FpFunctionsToExprsPass(val parseContext: ParseContext) : ProcedurePass { } if (found) { builder.removeEdge(edge) - builder.addEdge(XcfaEdge(edge.source, edge.target, SequenceLabel(newStmts))) + builder.addEdge(XcfaEdge(edge.source, edge.target, SequenceLabel(newStmts), edge.metadata)) } } return builder diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt index 48114fc020..3e1fad28db 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt @@ -90,15 +90,21 @@ class InlineProceduresPass(val parseContext: ParseContext) : ProcedurePass { val finalLoc = procedure.finalLoc val errorLoc = procedure.errorLoc - builder.addEdge(XcfaEdge(source, checkNotNull(newLocs[initLoc]), SequenceLabel(inStmts))) + builder.addEdge( + XcfaEdge(source, checkNotNull(newLocs[initLoc]), SequenceLabel(inStmts), e.metadata) + ) if (finalLoc.isPresent) builder.addEdge(XcfaEdge(checkNotNull(newLocs[finalLoc.get()]), target, - SequenceLabel(outStmts))) + SequenceLabel(outStmts), EmptyMetaData + ) + ) if (errorLoc.isPresent) { if (builder.errorLoc.isEmpty) builder.createErrorLoc() builder.addEdge( XcfaEdge(checkNotNull(newLocs[errorLoc.get()]), builder.errorLoc.get(), - SequenceLabel(listOf()))) + SequenceLabel(listOf(NopLabel)), EmptyMetaData + ) + ) } } else { builder.addEdge(e) diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt index bc745cfe67..481d019cf0 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt @@ -220,7 +220,9 @@ class LbePass(val parseContext: ParseContext) : ProcedurePass { nondetLabel = NondetLabel(oldLabels) builder.removeEdge(edge) } - builder.addEdge(XcfaEdge(source, target, nondetLabel)) + builder.addEdge( + XcfaEdge(source, target, nondetLabel, combineMetadata(edgesToTarget.map(XcfaEdge::metadata))) + ) if (edgesToTarget.size >= 2 && !locationsToVisit.contains(key)) { locationsToVisit.add(key) } @@ -290,7 +292,12 @@ class LbePass(val parseContext: ParseContext) : ProcedurePass { val newLabels = mutableListOf() newLabels.addAll(inEdge.getFlatLabels()) newLabels.addAll(outEdge.getFlatLabels()) - builder.addEdge(XcfaEdge(inEdge.source, outEdge.target, SequenceLabel(newLabels))) + builder.addEdge( + XcfaEdge( + inEdge.source, outEdge.target, SequenceLabel(newLabels), + combineMetadata(inEdge.metadata, outEdge.metadata) + ) + ) } return true } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt index 2a2fc5ee60..0c34b94caa 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt @@ -112,7 +112,7 @@ class LoopUnrollPass : ProcedurePass { private fun copyBody(builder: XcfaProcedureBuilder, startLoc: XcfaLocation, index: Int, removeCond: Boolean) : XcfaLocation { val locs = loopLocs.associateWith { - val loc = XcfaLocation("${it.name}_loop${index}") + val loc = XcfaLocation("${it.name}_loop${index}", metadata = it.metadata) builder.addLoc(loc) loc } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt index 07a1b62bb9..c505d0e99b 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt @@ -77,7 +77,7 @@ class MallocFunctionPass(val parseContext: ParseContext) : ProcedurePass { builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel( listOf( StmtLabel(assign1, metadata = invokeLabel.metadata), - StmtLabel(assign2, metadata = invokeLabel.metadata))))) + StmtLabel(assign2, metadata = invokeLabel.metadata))), it.metadata)) } else { builder.addEdge(it) } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt index ffcda3e8bb..2737d1dbb1 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt @@ -34,7 +34,7 @@ class NoSideEffectPass(val parseContext: ParseContext) : ProcedurePass { builder.removeEdge(edge) edges.forEach { if (predicate((it.label as SequenceLabel).labels[0])) { - builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel(listOf(NopLabel)))) + builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel(listOf(NopLabel)), it.metadata)) } else { builder.addEdge(it) } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt index fd7dfcb847..9c2819461c 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt @@ -40,7 +40,7 @@ class NondetFunctionPass : ProcedurePass { val havoc = HavocStmt.of( (invokeLabel.params[0] as RefExpr<*>).decl as VarDecl<*>) builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel( - listOf(StmtLabel(havoc, metadata = invokeLabel.metadata))))) + listOf(StmtLabel(havoc, metadata = invokeLabel.metadata))), it.metadata)) } else { builder.addEdge(it) } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt index cb5c74b8cb..43594c362a 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt @@ -53,13 +53,13 @@ fun XcfaEdge.splitIf(function: (XcfaLabel) -> Boolean): List { val locations = ArrayList() locations.add(source) for (i in 2..(newLabels.size)) { - locations.add(XcfaLocation("loc" + XcfaLocation.uniqueCounter())) + locations.add(XcfaLocation("loc" + XcfaLocation.uniqueCounter(), metadata = EmptyMetaData)) } locations.add(target) val newEdges = ArrayList() for ((i, label) in newLabels.withIndex()) { - newEdges.add(XcfaEdge(locations[i], locations[i + 1], label)) + newEdges.add(XcfaEdge(locations[i], locations[i + 1], label, metadata)) } return newEdges } @@ -158,4 +158,9 @@ private fun XcfaProcedureBuilder.canInline(tally: LinkedList): Boolean { tally.pop() metaData[if (recursive) "recursive" else "canInline"] = Unit return !recursive -} \ No newline at end of file +} + +fun combineMetadata(vararg metaData: MetaData): MetaData = combineMetadata(metaData.toList()) + +fun combineMetadata(metaData: Collection): MetaData = + metaData.reduce { i1, i2 -> i1.combine(i2) } diff --git a/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt b/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt index 65a89e0533..456f2e4703 100644 --- a/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt +++ b/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt @@ -46,8 +46,7 @@ class GsonTest { private fun getGson(scope: XcfaScope, env: Env, newScope: Boolean): Gson { val gsonBuilder = GsonBuilder() lateinit var gson: Gson - gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, - StringTypeAdapter(xcfaLocationAdapter)) + gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, XcfaLocationAdapter { gson }) gsonBuilder.registerTypeHierarchyAdapter(XCFA::class.java, XcfaAdapter { gson }) gsonBuilder.registerTypeHierarchyAdapter(VarDecl::class.java, VarDeclAdapter({ gson }, scope, env, !newScope)) diff --git a/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java b/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java index 96c5899062..7a3a159a80 100644 --- a/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java +++ b/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java @@ -80,9 +80,9 @@ public static Collection data() { "src/test/resources/property/green_and_red.prop", true, "z3:4.13.0"}, - {"src/test/resources/model/trafficlight_v2.xsts", - "src/test/resources/property/green_and_red.prop", true, - "eldarica:2.1"}, +// {"src/test/resources/model/trafficlight_v2.xsts", +// "src/test/resources/property/green_and_red.prop", true, +// "eldarica:2.1"}, {"src/test/resources/model/trafficlight_v2.xsts", "src/test/resources/property/green_and_red.prop", true, From c15b70cd05d8c2c901ec2d67ae7af3ed96433c40 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:15:53 +0100 Subject: [PATCH 14/21] added portfolio as a default backend when dealing with --svcomp tasks --- .../src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 54e2c0d406..1d7d6d208b 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 @@ -66,7 +66,8 @@ class XcfaCli(private val args: Array) { "--disable-arg-generation", "--disable-chc-serialization", "--disable-c-serialization", - "--only-svcomp-witness" + "--only-svcomp-witness", + "--backend", "PORTFOLIO" ) ) } From 301319a7eb07490219a88a4991f97e589a62908f Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:17:20 +0100 Subject: [PATCH 15/21] Only adding backend if not explicitly specified --- .../src/main/java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 1d7d6d208b..e5370bdf2e 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 @@ -67,9 +67,11 @@ class XcfaCli(private val args: Array) { "--disable-chc-serialization", "--disable-c-serialization", "--only-svcomp-witness", - "--backend", "PORTFOLIO" ) ) + if (!remainingFlags.contains("--backend")) { + remainingFlags.addAll(listOf("--backend", "PORTFOLIO")) + } } while (remainingFlags.isNotEmpty()) { val nextArgs = remainingFlags.toTypedArray() From 606911caa6463bc09c62235abdd070457f823cb6 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:19:43 +0100 Subject: [PATCH 16/21] Formatted files --- .../grammar/function/FunctionVisitor.java | 353 ++-- .../model/statements/CStatement.java | 21 +- .../frontend/chc/ChcBackwardXcfaBuilder.java | 95 +- .../frontend/chc/ChcForwardXcfaBuilder.java | 51 +- .../java/hu/bme/mit/theta/c2xcfa/CMetaData.kt | 114 +- .../mit/theta/c2xcfa/FrontendXcfaBuilder.kt | 1702 +++++++++-------- .../litmus2xcfa/dsl/LitmusAArch64.java | 316 ++- .../bme/mit/theta/llvm2xcfa/LlvmMetadata.java | 4 +- .../hu/bme/mit/theta/llvm2xcfa/Utils.java | 91 +- .../concrete/ArrayIntrinsicsHandler.java | 81 +- .../concrete/MemoryInstructionHandler.java | 96 +- .../concrete/OtherInstructionHandler.java | 264 ++- .../handlers/states/FunctionState.java | 69 +- .../bme/mit/theta/xcfa/analysis/XcfaAction.kt | 70 +- .../xcfa/analysis/XcfaExplAnalysisTest.kt | 4 +- .../xcfa/analysis/XcfaPredAnalysisTest.kt | 4 +- .../theta/xcfa/analysis/XcfaStateLtsTest.kt | 249 +-- subprojects/xcfa/xcfa-cli/build.gradle.kts | 1 - .../java/hu/bme/mit/theta/xcfa/cli/XcfaCli.kt | 173 +- .../xcfa/cli/utils/GraphmlWitnessWriter.kt | 200 +- .../bme/mit/theta/xcfa/cli/utils/GsonUtils.kt | 192 +- .../theta/xcfa/cli/utils/YmlWitnessWriter.kt | 282 +-- .../theta/xcfa/cli/witnesses/CommonWitness.kt | 128 +- .../xcfa/cli/witnesses/GraphmlWitness.kt | 196 +- .../xcfa/cli/witnesses/TraceToWitness.kt | 345 ++-- .../cli/witnesses/XcfaTraceConcretizer.java | 50 +- .../theta/xcfa/cli/witnesses/YamlWitness.kt | 383 ++-- .../mit/theta/xcfa/cli/XcfaCliParseTest.kt | 513 ++--- .../mit/theta/xcfa/cli/XcfaCliProofTest.kt | 8 +- .../bme/mit/theta/xcfa/cli/YamlParseTest.kt | 84 +- .../hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt | 349 ++-- .../theta/xcfa/gson/XcfaLocationAdapter.kt | 75 +- .../java/hu/bme/mit/theta/xcfa/model/Dsl.kt | 470 ++--- .../hu/bme/mit/theta/xcfa/model/MetaData.kt | 18 +- .../java/hu/bme/mit/theta/xcfa/model/XCFA.kt | 217 ++- .../theta/xcfa/passes/EliminateSelfLoops.kt | 43 +- .../theta/xcfa/passes/EmptyEdgeRemovalPass.kt | 70 +- .../theta/xcfa/passes/ErrorLocationPass.kt | 58 +- .../theta/xcfa/passes/FinalLocationPass.kt | 67 +- .../xcfa/passes/FpFunctionsToExprsPass.kt | 583 +++--- .../theta/xcfa/passes/InlineProceduresPass.kt | 201 +- .../hu/bme/mit/theta/xcfa/passes/LbePass.kt | 504 ++--- .../mit/theta/xcfa/passes/LoopUnrollPass.kt | 494 ++--- .../theta/xcfa/passes/MallocFunctionPass.kt | 130 +- .../mit/theta/xcfa/passes/NoSideEffectPass.kt | 59 +- .../theta/xcfa/passes/NondetFunctionPass.kt | 61 +- .../hu/bme/mit/theta/xcfa/passes/Utils.kt | 240 +-- .../hu/bme/mit/theta/xcfa/gson/GsonTest.kt | 144 +- .../mit/theta/xsts/analysis/XstsHornTest.java | 807 +++++--- 49 files changed, 6147 insertions(+), 4582 deletions(-) diff --git a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java index e4dbd1a5c8..d45fe00e83 100644 --- a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java +++ b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/grammar/function/FunctionVisitor.java @@ -13,9 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.frontend.transformation.grammar.function; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.decl.Decls.Var; +import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Add; +import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Ite; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; +import static hu.bme.mit.theta.grammar.UtilsKt.textWithWS; + import hu.bme.mit.theta.c.frontend.dsl.gen.CBaseVisitor; import hu.bme.mit.theta.c.frontend.dsl.gen.CParser; import hu.bme.mit.theta.common.Tuple2; @@ -47,24 +53,17 @@ import hu.bme.mit.theta.frontend.transformation.model.types.complex.CVoid; import hu.bme.mit.theta.frontend.transformation.model.types.simple.CSimpleType; import hu.bme.mit.theta.frontend.transformation.model.types.simple.Struct; -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.Token; - import java.util.*; import java.util.stream.Stream; - -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.decl.Decls.Var; -import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Add; -import static hu.bme.mit.theta.core.type.abstracttype.AbstractExprs.Ite; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; -import static hu.bme.mit.theta.grammar.UtilsKt.textWithWS; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; /** - * FunctionVisitor is responsible for the instantiation of high-level model elements, such as Programs, Functions, - * and Statements. It employs a TypeVisitor instance to provide type information, a DeclarationVisitor instance to - * provide information on declarations (both global and local, complete with initializations) and an ExpressionVisitor - * instance to provide information on Expressions in the source code. + * FunctionVisitor is responsible for the instantiation of high-level model elements, such as + * Programs, Functions, and Statements. It employs a TypeVisitor instance to provide type + * information, a DeclarationVisitor instance to provide information on declarations (both global + * and local, complete with initializations) and an ExpressionVisitor instance to provide + * information on Expressions in the source code. */ public class FunctionVisitor extends CBaseVisitor { private final ParseContext parseContext; @@ -94,21 +93,24 @@ private void createVars(CDeclaration declaration) { private String getName(final String name) { final StringJoiner sj = new StringJoiner("::"); - for (Iterator>>> iterator = variables.descendingIterator(); iterator.hasNext(); ) { + for (Iterator>>> iterator = + variables.descendingIterator(); + iterator.hasNext(); ) { Tuple2>> variable = iterator.next(); - if (!variable.get1().equals("")) - sj.add(variable.get1()); + if (!variable.get1().equals("")) sj.add(variable.get1()); } sj.add(name); return sj.toString(); } private void createVars(String name, CDeclaration declaration, CComplexType type) { -// checkState(declaration.getArrayDimensions().size() <= 1, "Currently, higher dimension arrays not supported"); + // checkState(declaration.getArrayDimensions().size() <= 1, "Currently, higher + // dimension arrays not supported"); Tuple2>> peek = variables.peek(); VarDecl varDecl = Var(getName(name), type.getSmtType()); if (peek.get2().containsKey(name)) { - uniqueWarningLogger.write(Level.INFO, "WARNING: Variable already exists: " + name + "\n"); + uniqueWarningLogger.write( + Level.INFO, "WARNING: Variable already exists: " + name + "\n"); varDecl = peek.get2().get(name); } peek.get2().put(name, varDecl); @@ -141,19 +143,27 @@ public CStatement visitCompilationUnit(CParser.CompilationUnitContext ctx) { // ExpressionVisitor.setBitwise(ctx.accept(BitwiseChecker.instance)); ctx.accept(typedefVisitor); - List globalUsages = globalDeclUsageVisitor.getGlobalUsages(ctx); + List globalUsages = + globalDeclUsageVisitor.getGlobalUsages(ctx); // if arithemetic is set on efficient, we change it to either bv or int arithmetic here - if (parseContext.getArithmetic() == ArchitectureConfig.ArithmeticType.efficient) { // if it wasn't on efficient, the check returns manual - Set arithmeticTraits = BitwiseChecker.gatherArithmeticTraits(parseContext, globalUsages); + if (parseContext.getArithmetic() + == ArchitectureConfig.ArithmeticType + .efficient) { // if it wasn't on efficient, the check returns manual + Set arithmeticTraits = + BitwiseChecker.gatherArithmeticTraits(parseContext, globalUsages); parseContext.setArithmetic( - arithmeticTraits.contains(ArithmeticTrait.BITWISE) || arithmeticTraits.contains(ArithmeticTrait.FLOAT) ? - ArithmeticType.bitvector : ArithmeticType.integer); + arithmeticTraits.contains(ArithmeticTrait.BITWISE) + || arithmeticTraits.contains(ArithmeticTrait.FLOAT) + ? ArithmeticType.bitvector + : ArithmeticType.integer); } Set typedefs = ctx.accept(typedefVisitor); for (CDeclaration typedef : typedefs) { - parseContext.getMetadata().create(typedef.getName(), "cTypedefName", typedef.getActualType()); + parseContext + .getMetadata() + .create(typedef.getName(), "cTypedefName", typedef.getActualType()); } CProgram program = new CProgram(parseContext); @@ -171,7 +181,8 @@ public CStatement visitCompilationUnit(CParser.CompilationUnitContext ctx) { public void recordMetadata(ParserRuleContext ctx, CStatement statement) { if (currentStatementContext != null) { - ctx = currentStatementContext; // this will overwrite the current ASt element's ctx with the statement's ctx + ctx = currentStatementContext; // this will overwrite the current ASt element's ctx + // with the statement's ctx } Token start = ctx.getStart(); Token stop = ctx.getStop(); @@ -181,7 +192,10 @@ public void recordMetadata(ParserRuleContext ctx, CStatement statement) { int lineNumberStart = start.getLine(); int colNumberStart = start.getCharPositionInLine(); int lineNumberStop = stop.getLine() + stopLines; - int colNumberStop = stopLines == 0 ? stop.getCharPositionInLine() + stopText.length() - 1 : stopTextLines[stopLines].length(); + int colNumberStop = + stopLines == 0 + ? stop.getCharPositionInLine() + stopText.length() - 1 + : stopTextLines[stopLines].length(); int offsetStart = start.getStartIndex(); int offsetEnd = stop.getStopIndex(); statement.setLineNumberStart(lineNumberStart); @@ -194,14 +208,17 @@ public void recordMetadata(ParserRuleContext ctx, CStatement statement) { statement.setCtx(ctx); } - @Override public CStatement visitGlobalDeclaration(CParser.GlobalDeclarationContext ctx) { - List declarations = declarationVisitor.getDeclarations(ctx.declaration().declarationSpecifiers(), ctx.declaration().initDeclaratorList()); + List declarations = + declarationVisitor.getDeclarations( + ctx.declaration().declarationSpecifiers(), + ctx.declaration().initDeclaratorList()); CDecls decls = new CDecls(parseContext); for (CDeclaration declaration : declarations) { if (!declaration.getType().isTypedef()) { - if (!declaration.isFunc()) { // functions should not be interpreted as global variables + if (!declaration + .isFunc()) { // functions should not be interpreted as global variables createVars(declaration); for (VarDecl varDecl : declaration.getVarDecls()) { decls.getcDeclarations().add(Tuple2.of(declaration, varDecl)); @@ -210,7 +227,9 @@ public CStatement visitGlobalDeclaration(CParser.GlobalDeclarationContext ctx) { CSimpleType returnType = declaration.getType(); declaration.setType(returnType); if (!variables.peek().get2().containsKey(declaration.getName())) { - parseContext.getMetadata().create(declaration.getName(), "cType", returnType.getActualType()); + parseContext + .getMetadata() + .create(declaration.getName(), "cType", returnType.getActualType()); createVars(declaration); for (VarDecl varDecl : declaration.getVarDecls()) { functions.put(varDecl, declaration); @@ -230,7 +249,9 @@ public CStatement visitFunctionDefinition(CParser.FunctionDefinitionContext ctx) CDeclaration funcDecl = ctx.declarator().accept(declarationVisitor); funcDecl.setType(returnType); if (!variables.peek().get2().containsKey(funcDecl.getName())) { - parseContext.getMetadata().create(funcDecl.getName(), "cType", returnType.getActualType()); + parseContext + .getMetadata() + .create(funcDecl.getName(), "cType", returnType.getActualType()); createVars(funcDecl); for (VarDecl varDecl : funcDecl.getVarDecls()) { functions.put(varDecl, funcDecl); @@ -239,20 +260,21 @@ public CStatement visitFunctionDefinition(CParser.FunctionDefinitionContext ctx) variables.push(Tuple2.of(funcDecl.getName(), new LinkedHashMap<>())); flatVariables.clear(); for (CDeclaration functionParam : funcDecl.getFunctionParams()) { - if (functionParam.getName() != null) - createVars(functionParam); + if (functionParam.getName() != null) createVars(functionParam); } CParser.BlockItemListContext blockItemListContext = ctx.compoundStatement().blockItemList(); if (blockItemListContext != null) { CStatement accept = blockItemListContext.accept(this); variables.pop(); - CFunction cFunction = new CFunction(funcDecl, accept, new ArrayList<>(flatVariables), parseContext); + CFunction cFunction = + new CFunction(funcDecl, accept, new ArrayList<>(flatVariables), parseContext); recordMetadata(ctx, cFunction); return cFunction; } variables.pop(); CCompound cCompound = new CCompound(parseContext); - CFunction cFunction = new CFunction(funcDecl, cCompound, new ArrayList<>(flatVariables), parseContext); + CFunction cFunction = + new CFunction(funcDecl, cCompound, new ArrayList<>(flatVariables), parseContext); recordMetadata(ctx, cCompound); recordMetadata(ctx, cFunction); return cFunction; @@ -288,10 +310,20 @@ public CStatement visitIdentifierStatement(CParser.IdentifierStatementContext ct @Override public CStatement visitCaseStatement(CParser.CaseStatementContext ctx) { parseContext.getCStmtCounter().incrementBranches(); - CExpr cexpr = new CExpr(ctx.constantExpression().accept(new ExpressionVisitor(parseContext, this, variables, functions, typedefVisitor, typeVisitor, uniqueWarningLogger)), parseContext); - CCase cCase = new CCase( - cexpr, - ctx.statement().accept(this), parseContext); + CExpr cexpr = + new CExpr( + ctx.constantExpression() + .accept( + new ExpressionVisitor( + parseContext, + this, + variables, + functions, + typedefVisitor, + typeVisitor, + uniqueWarningLogger)), + parseContext); + CCase cCase = new CCase(cexpr, ctx.statement().accept(this), parseContext); recordMetadata(ctx, cCase); recordMetadata(ctx.constantExpression(), cexpr); return cCase; @@ -316,7 +348,10 @@ public CStatement visitCompoundStatement(CParser.CompoundStatementContext ctx) { @Override public CStatement visitExpressionStatement(CParser.ExpressionStatementContext ctx) { - CStatement statement = ctx.expression() == null ? new CCompound(parseContext) : ctx.expression().accept(this); + CStatement statement = + ctx.expression() == null + ? new CCompound(parseContext) + : ctx.expression().accept(this); recordMetadata(ctx, statement); return statement; } @@ -325,10 +360,12 @@ public CStatement visitExpressionStatement(CParser.ExpressionStatementContext ct public CStatement visitIfStatement(CParser.IfStatementContext ctx) { parseContext.getCStmtCounter().incrementBranches(); variables.push(Tuple2.of("if" + anonCnt++, new LinkedHashMap<>())); - CIf cIf = new CIf( - ctx.expression().accept(this), - ctx.statement(0).accept(this), - ctx.statement().size() > 1 ? ctx.statement(1).accept(this) : null, parseContext); + CIf cIf = + new CIf( + ctx.expression().accept(this), + ctx.statement(0).accept(this), + ctx.statement().size() > 1 ? ctx.statement(1).accept(this) : null, + parseContext); recordMetadata(ctx, cIf); variables.pop(); return cIf; @@ -337,9 +374,9 @@ public CStatement visitIfStatement(CParser.IfStatementContext ctx) { @Override public CStatement visitSwitchStatement(CParser.SwitchStatementContext ctx) { variables.push(Tuple2.of("switch" + anonCnt++, new LinkedHashMap<>())); - CSwitch cSwitch = new CSwitch( - ctx.expression().accept(this), - ctx.statement().accept(this), parseContext); + CSwitch cSwitch = + new CSwitch( + ctx.expression().accept(this), ctx.statement().accept(this), parseContext); recordMetadata(ctx, cSwitch); variables.pop(); return cSwitch; @@ -349,9 +386,9 @@ public CStatement visitSwitchStatement(CParser.SwitchStatementContext ctx) { public CStatement visitWhileStatement(CParser.WhileStatementContext ctx) { parseContext.getCStmtCounter().incrementWhileLoops(); variables.push(Tuple2.of("while" + anonCnt++, new LinkedHashMap<>())); - CWhile cWhile = new CWhile( - ctx.statement().accept(this), - ctx.expression().accept(this), parseContext); + CWhile cWhile = + new CWhile( + ctx.statement().accept(this), ctx.expression().accept(this), parseContext); recordMetadata(ctx, cWhile); variables.pop(); return cWhile; @@ -360,9 +397,9 @@ public CStatement visitWhileStatement(CParser.WhileStatementContext ctx) { @Override public CStatement visitDoWhileStatement(CParser.DoWhileStatementContext ctx) { variables.push(Tuple2.of("dowhile" + anonCnt++, new LinkedHashMap<>())); - CDoWhile cDoWhile = new CDoWhile( - ctx.statement().accept(this), - ctx.expression().accept(this), parseContext); + CDoWhile cDoWhile = + new CDoWhile( + ctx.statement().accept(this), ctx.expression().accept(this), parseContext); recordMetadata(ctx, cDoWhile); variables.pop(); return cDoWhile; @@ -381,7 +418,9 @@ public CStatement visitForStatement(CParser.ForStatementContext ctx) { CCompound newCCompound4 = new CCompound(parseContext); newCCompound1.getcStatementList().add(newCCompound2); Expr one = CComplexType.getSignedInt(parseContext).getUnitValue(); - parseContext.getMetadata().create(one, "cType", CComplexType.getSignedInt(parseContext)); + parseContext + .getMetadata() + .create(one, "cType", CComplexType.getSignedInt(parseContext)); newCCompound2.getcStatementList().add(new CExpr(one, parseContext)); newCCompound2.setPreStatements(newCCompound3); newCCompound2.setPostStatements(newCCompound4); @@ -389,11 +428,7 @@ public CStatement visitForStatement(CParser.ForStatementContext ctx) { recordMetadata(ctx.forCondition(), test); } CStatement incr = ctx.forCondition().forIncr().accept(this); - CFor cFor = new CFor( - ctx.statement().accept(this), - init, - test, - incr, parseContext); + CFor cFor = new CFor(ctx.statement().accept(this), init, test, incr, parseContext); recordMetadata(ctx, cFor); variables.pop(); return cFor; @@ -422,7 +457,10 @@ public CStatement visitBreakStatement(CParser.BreakStatementContext ctx) { @Override public CStatement visitReturnStatement(CParser.ReturnStatementContext ctx) { - CRet cRet = new CRet(ctx.expression() == null ? null : ctx.expression().accept(this), parseContext); + CRet cRet = + new CRet( + ctx.expression() == null ? null : ctx.expression().accept(this), + parseContext); recordMetadata(ctx, cRet); return cRet; } @@ -438,44 +476,73 @@ public CStatement visitStatement(CParser.StatementContext ctx) { @Override public CStatement visitBodyDeclaration(CParser.BodyDeclarationContext ctx) { - List declarations = declarationVisitor.getDeclarations(ctx.declaration().declarationSpecifiers(), ctx.declaration().initDeclaratorList()); + List declarations = + declarationVisitor.getDeclarations( + ctx.declaration().declarationSpecifiers(), + ctx.declaration().initDeclaratorList()); CCompound compound = new CCompound(parseContext); for (CDeclaration declaration : declarations) { if (declaration.getInitExpr() != null) { createVars(declaration); if (declaration.getType() instanceof Struct) { - checkState(declaration.getInitExpr() instanceof CInitializerList, "Struct can only be initialized via an initializer list!"); + checkState( + declaration.getInitExpr() instanceof CInitializerList, + "Struct can only be initialized via an initializer list!"); final var initializerList = (CInitializerList) declaration.getInitExpr(); List> varDecls = declaration.getVarDecls(); VarDecl varDecl = varDecls.get(0); final var ptrType = CComplexType.getUnsignedLong(parseContext); LitExpr currentValue = ptrType.getNullValue(); LitExpr unitValue = ptrType.getUnitValue(); - for (Tuple2, CStatement> statement : initializerList.getStatements()) { + for (Tuple2, CStatement> statement : + initializerList.getStatements()) { final var expr = statement.get2().getExpression(); - final var deref = Exprs.Dereference(cast(varDecl.getRef(), currentValue.getType()), cast(currentValue, currentValue.getType()), expr.getType()); - CAssignment cAssignment = new CAssignment(deref, statement.get2(), "=", parseContext); + final var deref = + Exprs.Dereference( + cast(varDecl.getRef(), currentValue.getType()), + cast(currentValue, currentValue.getType()), + expr.getType()); + CAssignment cAssignment = + new CAssignment(deref, statement.get2(), "=", parseContext); recordMetadata(ctx, cAssignment); compound.getcStatementList().add(cAssignment); - currentValue = Add(currentValue, unitValue).eval(ImmutableValuation.empty()); + currentValue = + Add(currentValue, unitValue).eval(ImmutableValuation.empty()); } } else { - checkState(declaration.getVarDecls().size() == 1, "non-struct declarations shall only have one variable!"); + checkState( + declaration.getVarDecls().size() == 1, + "non-struct declarations shall only have one variable!"); if (declaration.getInitExpr() instanceof CInitializerList initializerList) { final var ptrType = CComplexType.getUnsignedLong(parseContext); LitExpr currentValue = ptrType.getNullValue(); LitExpr unitValue = ptrType.getUnitValue(); - for (Tuple2, CStatement> statement : initializerList.getStatements()) { -// checkState(false, "Code here seems to be buggy"); + for (Tuple2, CStatement> statement : + initializerList.getStatements()) { + // checkState(false, "Code here seems to be + // buggy"); final var expr = statement.get2().getExpression(); - final var deref = Exprs.Dereference(cast(declaration.getVarDecls().get(0).getRef(), currentValue.getType()), cast(currentValue, currentValue.getType()), expr.getType()); - CAssignment cAssignment = new CAssignment(deref, statement.get2(), "=", parseContext); + final var deref = + Exprs.Dereference( + cast( + declaration.getVarDecls().get(0).getRef(), + currentValue.getType()), + cast(currentValue, currentValue.getType()), + expr.getType()); + CAssignment cAssignment = + new CAssignment(deref, statement.get2(), "=", parseContext); recordMetadata(ctx, cAssignment); compound.getcStatementList().add(cAssignment); - currentValue = Add(currentValue, unitValue).eval(ImmutableValuation.empty()); + currentValue = + Add(currentValue, unitValue).eval(ImmutableValuation.empty()); } } else { - CAssignment cAssignment = new CAssignment(declaration.getVarDecls().get(0).getRef(), declaration.getInitExpr(), "=", parseContext); + CAssignment cAssignment = + new CAssignment( + declaration.getVarDecls().get(0).getRef(), + declaration.getInitExpr(), + "=", + parseContext); recordMetadata(ctx, cAssignment); compound.getcStatementList().add(cAssignment); if (declaration.getInitExpr() instanceof CCompound compoundInitExpr) { @@ -494,19 +561,31 @@ public CStatement visitBodyDeclaration(CParser.BodyDeclarationContext ctx) { } } else { createVars(declaration); - // if there is no initializer, then we'll add an assumption regarding min and max values + // if there is no initializer, then we'll add an assumption regarding min and max + // values if (declaration.getType() instanceof Struct) { for (VarDecl varDecl : declaration.getVarDecls()) { - if (!(varDecl.getType() instanceof ArrayType) && !(varDecl.getType() instanceof BoolType)) { // BoolType is either well-defined true/false, or a struct in disguise - AssumeStmt assumeStmt = CComplexType.getType(varDecl.getRef(), parseContext).limit(varDecl.getRef()); + if (!(varDecl.getType() instanceof ArrayType) + && !(varDecl.getType() + instanceof + BoolType)) { // BoolType is either well-defined true/false, + // or a struct in disguise + AssumeStmt assumeStmt = + CComplexType.getType(varDecl.getRef(), parseContext) + .limit(varDecl.getRef()); CAssume cAssume = new CAssume(assumeStmt, parseContext); compound.getcStatementList().add(cAssume); } } } else { VarDecl varDecl = declaration.getVarDecls().get(0); - if (!(varDecl.getType() instanceof ArrayType) && !(varDecl.getType() instanceof BoolType) && !(CComplexType.getType(varDecl.getRef(), parseContext) instanceof CVoid)) { - AssumeStmt assumeStmt = CComplexType.getType(varDecl.getRef(), parseContext).limit(varDecl.getRef()); + if (!(varDecl.getType() instanceof ArrayType) + && !(varDecl.getType() instanceof BoolType) + && !(CComplexType.getType(varDecl.getRef(), parseContext) + instanceof CVoid)) { + AssumeStmt assumeStmt = + CComplexType.getType(varDecl.getRef(), parseContext) + .limit(varDecl.getRef()); CAssume cAssume = new CAssume(assumeStmt, parseContext); compound.getcStatementList().add(cAssume); } @@ -520,7 +599,8 @@ public CStatement visitBodyDeclaration(CParser.BodyDeclarationContext ctx) { @Override public CStatement visitExpression(CParser.ExpressionContext ctx) { CCompound compound = new CCompound(parseContext); - for (CParser.AssignmentExpressionContext assignmentExpressionContext : ctx.assignmentExpression()) { + for (CParser.AssignmentExpressionContext assignmentExpressionContext : + ctx.assignmentExpression()) { compound.getcStatementList().add(assignmentExpressionContext.accept(this)); } recordMetadata(ctx, compound); @@ -528,8 +608,17 @@ public CStatement visitExpression(CParser.ExpressionContext ctx) { } @Override - public CStatement visitAssignmentExpressionAssignmentExpression(CParser.AssignmentExpressionAssignmentExpressionContext ctx) { - ExpressionVisitor expressionVisitor = new ExpressionVisitor(parseContext, this, variables, functions, typedefVisitor, typeVisitor, uniqueWarningLogger); + public CStatement visitAssignmentExpressionAssignmentExpression( + CParser.AssignmentExpressionAssignmentExpressionContext ctx) { + ExpressionVisitor expressionVisitor = + new ExpressionVisitor( + parseContext, + this, + variables, + functions, + typedefVisitor, + typeVisitor, + uniqueWarningLogger); CCompound compound = new CCompound(parseContext); CCompound preStatements = new CCompound(parseContext); CCompound postStatements = new CCompound(parseContext); @@ -543,7 +632,8 @@ public CStatement visitAssignmentExpressionAssignmentExpression(CParser.Assignme resetPreStatements(compoundInitExpr); resetPostStatements(compoundInitExpr); } - CAssignment cAssignment = new CAssignment(ret, rhs, ctx.assignmentOperator().getText(), parseContext); + CAssignment cAssignment = + new CAssignment(ret, rhs, ctx.assignmentOperator().getText(), parseContext); compound.getcStatementList().add(cAssignment); preStatements.getcStatementList().addAll(expressionVisitor.getPreStatements()); compound.setPreStatements(preStatements); @@ -555,7 +645,8 @@ public CStatement visitAssignmentExpressionAssignmentExpression(CParser.Assignme } @Override - public CStatement visitAssignmentExpressionConditionalExpression(CParser.AssignmentExpressionConditionalExpressionContext ctx) { + public CStatement visitAssignmentExpressionConditionalExpression( + CParser.AssignmentExpressionConditionalExpressionContext ctx) { return ctx.conditionalExpression().accept(this); } @@ -579,7 +670,9 @@ private void resetPostStatements(CStatement statement) { private List getStatementList(CStatement statement) { if (statement instanceof CCompound compound) { - return compound.getcStatementList().stream().flatMap(i -> getStatementList(i).stream()).toList(); + return compound.getcStatementList().stream() + .flatMap(i -> getStatementList(i).stream()) + .toList(); } else if (statement != null) { return List.of(statement); } else { @@ -596,11 +689,17 @@ private List getStatementList(CStatement statement) { private List collectPreStatements(CStatement cStatement) { if (cStatement instanceof CCompound) { return Stream.concat( - Stream.concat( - collectPreStatements(cStatement.getPreStatements()).stream(), - getStatementList(cStatement.getPreStatements()).stream()), - ((CCompound) cStatement).getcStatementList().stream().flatMap(cStatement1 -> collectPreStatements(cStatement1).stream()) - ).filter(i -> !(i instanceof CExpr)).toList(); + Stream.concat( + collectPreStatements(cStatement.getPreStatements()).stream(), + getStatementList(cStatement.getPreStatements()).stream()), + ((CCompound) cStatement) + .getcStatementList().stream() + .flatMap( + cStatement1 -> + collectPreStatements(cStatement1) + .stream())) + .filter(i -> !(i instanceof CExpr)) + .toList(); } else return List.of(); } @@ -613,11 +712,17 @@ private List collectPreStatements(CStatement cStatement) { private List collectPostStatements(CStatement cStatement) { if (cStatement instanceof CCompound) { return Stream.concat( - ((CCompound) cStatement).getcStatementList().stream().flatMap(cStatement1 -> collectPostStatements(cStatement1).stream()), - Stream.concat( - getStatementList(cStatement.getPostStatements()).stream(), - collectPostStatements(cStatement.getPostStatements()).stream()) - ).filter(i -> !(i instanceof CExpr)).toList(); + ((CCompound) cStatement) + .getcStatementList().stream() + .flatMap( + cStatement1 -> + collectPostStatements(cStatement1) + .stream()), + Stream.concat( + getStatementList(cStatement.getPostStatements()).stream(), + collectPostStatements(cStatement.getPostStatements()).stream())) + .filter(i -> !(i instanceof CExpr)) + .toList(); } else return List.of(); } @@ -630,7 +735,15 @@ public CStatement visitConditionalExpression(CParser.ConditionalExpressionContex CCompound preStatements = new CCompound(parseContext); CCompound postStatements = new CCompound(parseContext); - ExpressionVisitor expressionVisitor = new ExpressionVisitor(parseContext, this, variables, functions, typedefVisitor, typeVisitor, uniqueWarningLogger); + ExpressionVisitor expressionVisitor = + new ExpressionVisitor( + parseContext, + this, + variables, + functions, + typedefVisitor, + typeVisitor, + uniqueWarningLogger); Expr iteExpr; if (!ctx.expression().isEmpty()) { @@ -646,7 +759,6 @@ public CStatement visitConditionalExpression(CParser.ConditionalExpressionContex guardCompound.setPostStatements(new CCompound(parseContext)); guardCompound.setPreStatements(new CCompound(parseContext)); - CCompound ifTruePre = new CCompound(parseContext); List ifTruePreList = collectPreStatements(ifTrue); ifTruePre.getcStatementList().addAll(ifTruePreList); @@ -669,20 +781,29 @@ public CStatement visitConditionalExpression(CParser.ConditionalExpressionContex ifFalsePost.setPostStatements(new CCompound(parseContext)); ifFalsePost.setPreStatements(new CCompound(parseContext)); - if (!ifTruePreList.isEmpty() || !ifFalsePreList.isEmpty()) { - preStatements.getcStatementList().add(new CIf(guardCompound, ifTruePre, ifFalsePre, parseContext)); + preStatements + .getcStatementList() + .add(new CIf(guardCompound, ifTruePre, ifFalsePre, parseContext)); } if (!ifTruePostList.isEmpty() || !ifFalsePostList.isEmpty()) { - postStatements.getcStatementList().add(new CIf(guardCompound, ifTruePost, ifFalsePost, parseContext)); + postStatements + .getcStatementList() + .add(new CIf(guardCompound, ifTruePost, ifFalsePost, parseContext)); } - CComplexType smallestCommonType = CComplexType.getSmallestCommonType(List.of(CComplexType.getType(lhs, parseContext), CComplexType.getType(rhs, parseContext)), parseContext); - IteExpr ite = Ite( - AbstractExprs.Neq(CComplexType.getType(expr, parseContext).getNullValue(), expr), - smallestCommonType.castTo(lhs), - smallestCommonType.castTo(rhs) - ); + CComplexType smallestCommonType = + CComplexType.getSmallestCommonType( + List.of( + CComplexType.getType(lhs, parseContext), + CComplexType.getType(rhs, parseContext)), + parseContext); + IteExpr ite = + Ite( + AbstractExprs.Neq( + CComplexType.getType(expr, parseContext).getNullValue(), expr), + smallestCommonType.castTo(lhs), + smallestCommonType.castTo(rhs)); parseContext.getMetadata().create(ite, "cType", smallestCommonType); iteExpr = ite; } else { @@ -702,12 +823,21 @@ public CStatement visitConditionalExpression(CParser.ConditionalExpressionContex @Override public CStatement visitForDeclaration(CParser.ForDeclarationContext ctx) { - List declarations = declarationVisitor.getDeclarations(ctx.declarationSpecifiers(), ctx.initDeclaratorList()); + List declarations = + declarationVisitor.getDeclarations( + ctx.declarationSpecifiers(), ctx.initDeclaratorList()); CCompound compound = new CCompound(parseContext); for (CDeclaration declaration : declarations) { createVars(declaration); - checkState(declaration.getVarDecls().size() == 1, "For loops cannot have struct declarations! (not yet implemented)"); - CAssignment cAssignment = new CAssignment(declaration.getVarDecls().get(0).getRef(), declaration.getInitExpr(), "=", parseContext); + checkState( + declaration.getVarDecls().size() == 1, + "For loops cannot have struct declarations! (not yet implemented)"); + CAssignment cAssignment = + new CAssignment( + declaration.getVarDecls().get(0).getRef(), + declaration.getInitExpr(), + "=", + parseContext); recordMetadata(ctx, cAssignment); if (declaration.getInitExpr() != null) compound.getcStatementList().add(cAssignment); } @@ -718,7 +848,8 @@ public CStatement visitForDeclaration(CParser.ForDeclarationContext ctx) { @Override public CStatement visitForExpression(CParser.ForExpressionContext ctx) { CCompound compound = new CCompound(parseContext); - for (CParser.AssignmentExpressionContext assignmentExpressionContext : ctx.assignmentExpression()) { + for (CParser.AssignmentExpressionContext assignmentExpressionContext : + ctx.assignmentExpression()) { compound.getcStatementList().add(assignmentExpressionContext.accept(this)); } recordMetadata(ctx, compound); diff --git a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java index 7b569aada4..989f18d3b8 100644 --- a/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java +++ b/subprojects/frontends/c-frontend/src/main/java/hu/bme/mit/theta/frontend/transformation/model/statements/CStatement.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.frontend.transformation.model.statements; import hu.bme.mit.theta.core.type.Expr; @@ -22,9 +21,9 @@ import org.antlr.v4.runtime.ParserRuleContext; /** - * Every Program, Function and Statement is a subclass of this base class. - * Any CStatement might have an id associated with it, in case there was a label in the source code. This also provides - * an XcfaLocation, which can be used when jumping to this named location via a _goto_ instruction + * Every Program, Function and Statement is a subclass of this base class. Any CStatement might have + * an id associated with it, in case there was a label in the source code. This also provides an + * XcfaLocation, which can be used when jumping to this named location via a _goto_ instruction */ public abstract class CStatement { protected final ParseContext parseContext; @@ -55,10 +54,10 @@ public void setId(String id) { } /** - * Returns the expression associated with a CStatement, which by default throws an exception, as not all subtypes - * will return one. For example, the C language statement `int a = (b = 0, 2)` will create a CCompound statement as - * the right-hand side of the assignment, whose associated expression will be 2, but the assignment to b has to come - * beforehand. + * Returns the expression associated with a CStatement, which by default throws an exception, as + * not all subtypes will return one. For example, the C language statement `int a = (b = 0, 2)` + * will create a CCompound statement as the right-hand side of the assignment, whose associated + * expression will be 2, but the assignment to b has to come beforehand. * * @return The expression associated with the statement. */ @@ -71,7 +70,8 @@ public CStatement getPostStatements() { } public void setPostStatements(CStatement postStatements) { - throw new UnsupportedFrontendElementException("Only CCompounds shall currently have pre- and post statements!"); + throw new UnsupportedFrontendElementException( + "Only CCompounds shall currently have pre- and post statements!"); } public CStatement getPreStatements() { @@ -79,7 +79,8 @@ public CStatement getPreStatements() { } public void setPreStatements(CStatement preStatements) { - throw new UnsupportedFrontendElementException("Only CCompounds shall currently have pre- and post statements!"); + throw new UnsupportedFrontendElementException( + "Only CCompounds shall currently have pre- and post statements!"); } public abstract R accept(CStatementVisitor visitor, P param); diff --git a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java index f1d0ef9bca..9457748898 100644 --- a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java +++ b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcBackwardXcfaBuilder.java @@ -15,6 +15,12 @@ */ package hu.bme.mit.theta.frontend.chc; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; +import static hu.bme.mit.theta.frontend.chc.ChcUtils.createVars; +import static hu.bme.mit.theta.frontend.chc.ChcUtils.getTailConditionLabels; +import static hu.bme.mit.theta.frontend.chc.ChcUtils.transformConst; +import static hu.bme.mit.theta.frontend.chc.ChcUtils.transformSort; + import hu.bme.mit.theta.chc.frontend.dsl.gen.CHCBaseVisitor; import hu.bme.mit.theta.chc.frontend.dsl.gen.CHCParser; import hu.bme.mit.theta.core.decl.Decls; @@ -36,20 +42,13 @@ import hu.bme.mit.theta.xcfa.model.XcfaLocation; import hu.bme.mit.theta.xcfa.model.XcfaProcedureBuilder; import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager; -import kotlin.Pair; -import org.antlr.v4.runtime.RuleContext; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; - -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.createVars; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.getTailConditionLabels; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.transformConst; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.transformSort; +import kotlin.Pair; +import org.antlr.v4.runtime.RuleContext; public class ChcBackwardXcfaBuilder extends CHCBaseVisitor implements ChcXcfaBuilder { private final Map procedures = new HashMap<>(); @@ -67,8 +66,8 @@ public XcfaBuilder buildXcfa(CHCParser parser) { visit(parser.benchmark()); -// xcfaBuilder.addProcess(procBuilder); -// xcfaBuilder.setMainProcess(procBuilder); + // xcfaBuilder.addProcess(procBuilder); + // xcfaBuilder.setMainProcess(procBuilder); return xcfaBuilder; } @@ -103,9 +102,19 @@ public Object visitChc_assert(CHCParser.Chc_assertContext ctx) { vars.put(ctx.chc_head().u_pred_atom().symbol(i++).getText(), param.getFirst()); } XcfaLocation middle = createLocation(procedure); - XcfaEdge edge = new XcfaEdge(procedure.getInitLoc(), middle, new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars)), EmptyMetaData.INSTANCE); + XcfaEdge edge = + new XcfaEdge( + procedure.getInitLoc(), + middle, + new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars)), + EmptyMetaData.INSTANCE); procedure.addEdge(edge); - createCalls(procedure, middle, procedure.getFinalLoc().get(), ctx.chc_tail().u_pred_atom(), vars); + createCalls( + procedure, + middle, + procedure.getFinalLoc().get(), + ctx.chc_tail().u_pred_atom(), + vars); } else { String procName; if (ctx.chc_head() != null) { @@ -115,7 +124,12 @@ public Object visitChc_assert(CHCParser.Chc_assertContext ctx) { } procedure = procedures.get(procName); Stmt returnTrue = AssignStmt.create(getOutParam(procedure), BoolLitExpr.of(true)); - XcfaEdge edge = new XcfaEdge(procedure.getInitLoc(), procedure.getFinalLoc().get(), new StmtLabel(returnTrue), EmptyMetaData.INSTANCE); + XcfaEdge edge = + new XcfaEdge( + procedure.getInitLoc(), + procedure.getFinalLoc().get(), + new StmtLabel(returnTrue), + EmptyMetaData.INSTANCE); procedure.addEdge(edge); } return super.visitChc_assert(ctx); @@ -128,9 +142,19 @@ public Object visitChc_query(CHCParser.Chc_queryContext ctx) { Map> vars = createVars(mainProcedure, ctx.var_decl()); XcfaLocation middle = createLocation(mainProcedure); - XcfaEdge edge = new XcfaEdge(mainProcedure.getInitLoc(), middle, new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars)), EmptyMetaData.INSTANCE); + XcfaEdge edge = + new XcfaEdge( + mainProcedure.getInitLoc(), + middle, + new SequenceLabel(getTailConditionLabels(ctx.chc_tail(), vars)), + EmptyMetaData.INSTANCE); mainProcedure.addEdge(edge); - createCalls(mainProcedure, middle, mainProcedure.getErrorLoc().get(), ctx.chc_tail().u_pred_atom(), vars); + createCalls( + mainProcedure, + middle, + mainProcedure.getErrorLoc().get(), + ctx.chc_tail().u_pred_atom(), + vars); return super.visitChc_query(ctx); } @@ -156,29 +180,50 @@ private XcfaProcedureBuilder createProcedure(String procName) { } private VarDecl getOutParam(XcfaProcedureBuilder procedure) { - Optional, ParamDirection>> param = procedure.getParams() - .stream().filter(entry -> entry.getSecond() == ParamDirection.OUT).findAny(); + Optional, ParamDirection>> param = + procedure.getParams().stream() + .filter(entry -> entry.getSecond() == ParamDirection.OUT) + .findAny(); return param.map(Pair::getFirst).orElse(null); } - private void createCalls(XcfaProcedureBuilder builder, XcfaLocation start, XcfaLocation end, List uPreds, Map> localVars) { + private void createCalls( + XcfaProcedureBuilder builder, + XcfaLocation start, + XcfaLocation end, + List uPreds, + Map> localVars) { XcfaLocation from = start; for (CHCParser.U_pred_atomContext uPred : uPreds) { XcfaLocation middle = createLocation(builder); XcfaLocation to = createLocation(builder); XcfaProcedureBuilder calledProcedure = procedures.get(uPred.u_predicate().getText()); - VarDecl ret = Decls.Var(calledProcedure.getName() + "_ret_" + callCount++, Bool()); + VarDecl ret = + Decls.Var(calledProcedure.getName() + "_ret_" + callCount++, Bool()); builder.addVar(ret); localVars.put(ret.getName(), ret); - List paramNames = new ArrayList<>(uPred.symbol().stream().map(RuleContext::getText).toList()); + List paramNames = + new ArrayList<>(uPred.symbol().stream().map(RuleContext::getText).toList()); paramNames.add(0, ret.getName()); - List> params = paramNames.stream().map(s -> localVars.get(s).getRef()).toList(); - - XcfaEdge callEdge = new XcfaEdge(from, middle, new InvokeLabel(calledProcedure.getName(), params, EmptyMetaData.INSTANCE), EmptyMetaData.INSTANCE); + List> params = + paramNames.stream().map(s -> localVars.get(s).getRef()).toList(); + + XcfaEdge callEdge = + new XcfaEdge( + from, + middle, + new InvokeLabel( + calledProcedure.getName(), params, EmptyMetaData.INSTANCE), + EmptyMetaData.INSTANCE); builder.addEdge(callEdge); - XcfaEdge assertEdge = new XcfaEdge(middle, to, new StmtLabel(AssumeStmt.of(ret.getRef())), EmptyMetaData.INSTANCE); + XcfaEdge assertEdge = + new XcfaEdge( + middle, + to, + new StmtLabel(AssumeStmt.of(ret.getRef())), + EmptyMetaData.INSTANCE); builder.addEdge(assertEdge); from = to; diff --git a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java index 04f591c913..84f38db5b0 100644 --- a/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java +++ b/subprojects/frontends/chc-frontend/src/main/java/hu/bme/mit/theta/frontend/chc/ChcForwardXcfaBuilder.java @@ -15,6 +15,8 @@ */ package hu.bme.mit.theta.frontend.chc; +import static hu.bme.mit.theta.frontend.chc.ChcUtils.*; + import hu.bme.mit.theta.chc.frontend.dsl.gen.CHCBaseVisitor; import hu.bme.mit.theta.chc.frontend.dsl.gen.CHCParser; import hu.bme.mit.theta.core.decl.Decls; @@ -24,14 +26,11 @@ import hu.bme.mit.theta.core.type.Type; import hu.bme.mit.theta.xcfa.model.*; import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import static hu.bme.mit.theta.frontend.chc.ChcUtils.*; - public class ChcForwardXcfaBuilder extends CHCBaseVisitor implements ChcXcfaBuilder { private final ProcedurePassManager procedurePassManager; private XcfaProcedureBuilder builder; @@ -120,27 +119,42 @@ public Object visitChc_query(CHCParser.Chc_queryContext ctx) { List labels = new ArrayList<>(); labels.addAll(getIncomingAssignments(ctx.chc_tail(), vars)); labels.addAll(getTailConditionLabels(ctx.chc_tail(), vars)); - XcfaEdge edge = new XcfaEdge(from, errorLocation, new SequenceLabel(labels), EmptyMetaData.INSTANCE); + XcfaEdge edge = + new XcfaEdge( + from, errorLocation, new SequenceLabel(labels), EmptyMetaData.INSTANCE); builder.addEdge(edge); return super.visitChc_query(ctx); } - private List getIncomingAssignments(CHCParser.Chc_tailContext tail, Map> localVars) { + private List getIncomingAssignments( + CHCParser.Chc_tailContext tail, Map> localVars) { List labels = new ArrayList<>(); UPred from = locations.get(getTailFrom(tail).getName()); - tail.u_pred_atom().forEach(u_pred -> { - List> params = u_pred.symbol().stream().map(symbol -> localVars.get(symbol.getText())).toList(); - localVars.values().forEach(var -> { - if (!params.contains(var)) - labels.add(new StmtLabel(HavocStmt.of(var))); - }); - labels.addAll(getParamAssignments(params, from.vars)); - }); + tail.u_pred_atom() + .forEach( + u_pred -> { + List> params = + u_pred.symbol().stream() + .map(symbol -> localVars.get(symbol.getText())) + .toList(); + localVars + .values() + .forEach( + var -> { + if (!params.contains(var)) + labels.add(new StmtLabel(HavocStmt.of(var))); + }); + labels.addAll(getParamAssignments(params, from.vars)); + }); return labels; } - private List getTargetAssignments(CHCParser.Chc_headContext head, Map> localVars) { - List> params = head.u_pred_atom().symbol().stream().map(symbol -> localVars.get(symbol.getText())).toList(); + private List getTargetAssignments( + CHCParser.Chc_headContext head, Map> localVars) { + List> params = + head.u_pred_atom().symbol().stream() + .map(symbol -> localVars.get(symbol.getText())) + .toList(); UPred to = locations.get(getHeadTo(head).getName()); return getParamAssignments(to.vars, params); } @@ -149,7 +163,9 @@ private XcfaLocation getTailFrom(CHCParser.Chc_tailContext tail) { XcfaLocation from; if (tail.u_pred_atom() != null && !tail.u_pred_atom().isEmpty()) { if (tail.u_pred_atom().size() != 1) - throw new UnsupportedOperationException("Non-linear CHCs are not supported with forward transformation, try using the --chc-transformation BACKWARD flag."); + throw new UnsupportedOperationException( + "Non-linear CHCs are not supported with forward transformation, try using" + + " the --chc-transformation BACKWARD flag."); from = locations.get(tail.u_pred_atom().get(0).u_predicate().getText()).location; } else { from = initLocation; @@ -161,7 +177,8 @@ private XcfaLocation getHeadTo(CHCParser.Chc_headContext head) { return locations.get(head.u_pred_atom().u_predicate().getText()).location; } - private List getParamAssignments(List> lhs, List> rhs) { + private List getParamAssignments( + List> lhs, List> rhs) { List labels = new ArrayList<>(); for (int i = 0; i < lhs.size(); ++i) { labels.add(new StmtLabel(AssignStmt.create(lhs.get(i), rhs.get(i).getRef()))); diff --git a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt index d62b191661..9e10ca93f7 100644 --- a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt +++ b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/CMetaData.kt @@ -16,71 +16,83 @@ package hu.bme.mit.theta.c2xcfa import hu.bme.mit.theta.xcfa.model.* -import org.antlr.v4.runtime.ParserRuleContext import kotlin.math.max import kotlin.math.min data class CMetaData( - val lineNumberStart: Int?, - val colNumberStart: Int?, - val lineNumberStop: Int?, - val colNumberStop: Int?, - val offsetStart: Int?, - val offsetEnd: Int?, - val sourceText: String?, + val lineNumberStart: Int?, + val colNumberStart: Int?, + val lineNumberStop: Int?, + val colNumberStop: Int?, + val offsetStart: Int?, + val offsetEnd: Int?, + val sourceText: String?, ) : MetaData() { - override fun combine(other: MetaData): MetaData { - if (other is CMetaData) { - return CMetaData( - lineNumberStart = min( - lineNumberStart ?: other.lineNumberStart ?: -1, other.lineNumberStart ?: lineNumberStart ?: -1 - ).takeIf { it > 0 } ?: 0, - colNumberStart = min( - colNumberStart ?: other.colNumberStart ?: -1, other.colNumberStart ?: colNumberStart ?: -1 - ).takeIf { it > 0 } ?: 0, - offsetStart = min( - offsetStart ?: other.offsetStart ?: -1, other.offsetStart ?: offsetStart ?: -1 - ).takeIf { it > 0 } ?: 0, - lineNumberStop = max( - lineNumberStop ?: other.lineNumberStop ?: -1, other.lineNumberStop ?: lineNumberStop ?: -1 - ).takeIf { it > 0 } ?: 0, - colNumberStop = max( - colNumberStop ?: other.colNumberStop ?: -1, other.colNumberStop ?: colNumberStop ?: -1 - ).takeIf { it > 0 } ?: 0, - offsetEnd = max( - offsetEnd ?: other.offsetEnd ?: -1, other.offsetEnd ?: offsetEnd ?: -1 - ).takeIf { it > 0 } ?: 0, - sourceText = (sourceText ?: "") + (other.sourceText ?: ""), + override fun combine(other: MetaData): MetaData { + if (other is CMetaData) { + return CMetaData( + lineNumberStart = + min( + lineNumberStart ?: other.lineNumberStart ?: -1, + other.lineNumberStart ?: lineNumberStart ?: -1, ) - } else if (other is EmptyMetaData) { - return this - } else { - error("Cannot combine metadata of different types: $this vs $other") - } + .takeIf { it > 0 } ?: 0, + colNumberStart = + min( + colNumberStart ?: other.colNumberStart ?: -1, + other.colNumberStart ?: colNumberStart ?: -1, + ) + .takeIf { it > 0 } ?: 0, + offsetStart = + min(offsetStart ?: other.offsetStart ?: -1, other.offsetStart ?: offsetStart ?: -1) + .takeIf { it > 0 } ?: 0, + lineNumberStop = + max( + lineNumberStop ?: other.lineNumberStop ?: -1, + other.lineNumberStop ?: lineNumberStop ?: -1, + ) + .takeIf { it > 0 } ?: 0, + colNumberStop = + max( + colNumberStop ?: other.colNumberStop ?: -1, + other.colNumberStop ?: colNumberStop ?: -1, + ) + .takeIf { it > 0 } ?: 0, + offsetEnd = + max(offsetEnd ?: other.offsetEnd ?: -1, other.offsetEnd ?: offsetEnd ?: -1).takeIf { + it > 0 + } ?: 0, + sourceText = (sourceText ?: "") + (other.sourceText ?: ""), + ) + } else if (other is EmptyMetaData) { + return this + } else { + error("Cannot combine metadata of different types: $this vs $other") } + } } fun XcfaLabel.getCMetaData(): CMetaData? { - return if (this.metadata is CMetaData) { - this.metadata as CMetaData - } else { - null - } + return if (this.metadata is CMetaData) { + this.metadata as CMetaData + } else { + null + } } fun XcfaLocation.getCMetaData(): CMetaData? { - return if (this.metadata is CMetaData) { - this.metadata as CMetaData - } else { - null - } + return if (this.metadata is CMetaData) { + this.metadata as CMetaData + } else { + null + } } fun XcfaEdge.getCMetaData(): CMetaData? { - return if (this.metadata is CMetaData) { - this.metadata as CMetaData - } else { - null - } -} \ No newline at end of file + return if (this.metadata is CMetaData) { + this.metadata as CMetaData + } else { + null + } +} diff --git a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt index ebc4fd3da7..7c2ac51694 100644 --- a/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt +++ b/subprojects/xcfa/c2xcfa/src/main/java/hu/bme/mit/theta/c2xcfa/FrontendXcfaBuilder.kt @@ -50,814 +50,1002 @@ import hu.bme.mit.theta.frontend.transformation.model.types.complex.integer.CInt import hu.bme.mit.theta.frontend.transformation.model.types.simple.CSimpleTypeFactory import hu.bme.mit.theta.xcfa.model.* import hu.bme.mit.theta.xcfa.passes.CPasses -import org.abego.treelayout.internal.util.Contract.checkState import java.math.BigInteger import java.util.stream.Collectors +import org.abego.treelayout.internal.util.Contract.checkState -class FrontendXcfaBuilder(val parseContext: ParseContext, val checkOverflow: Boolean = false, - val uniqueWarningLogger: Logger) : - CStatementVisitorBase() { - - private val locationLut: MutableMap = LinkedHashMap() - private var ptrCnt = 1 // counts up, uses 3k+1 - get() = field.also { field += 3 } - - private fun getLoc(builder: XcfaProcedureBuilder, name: String?, - metadata: MetaData): XcfaLocation { - if (name == null) return getAnonymousLoc(builder, metadata = metadata) - locationLut.putIfAbsent(name, XcfaLocation(name, metadata = metadata)) - val location = locationLut[name] - builder.addLoc(checkNotNull(location)) - return location - } +class FrontendXcfaBuilder( + val parseContext: ParseContext, + val checkOverflow: Boolean = false, + val uniqueWarningLogger: Logger, +) : CStatementVisitorBase() { - private fun getAnonymousLoc(builder: XcfaProcedureBuilder, metadata: MetaData): XcfaLocation { - return getLoc(builder, "__loc_" + XcfaLocation.uniqueCounter(), metadata) - } + private val locationLut: MutableMap = LinkedHashMap() + private var ptrCnt = 1 // counts up, uses 3k+1 + get() = field.also { field += 3 } - private fun getMetadata(source: CStatement): CMetaData = CMetaData( - lineNumberStart = source.lineNumberStart.takeIf { it != -1 }, - lineNumberStop = source.lineNumberStop.takeIf { it != -1 }, - colNumberStart = source.colNumberStart.takeIf { it != -1 }, - colNumberStop = source.colNumberStop.takeIf { it != -1 }, - offsetStart = source.offsetStart.takeIf { it != -1 }, - offsetEnd = source.offsetEnd.takeIf { it != -1 }, - sourceText = source.sourceText, - ) + private fun getLoc( + builder: XcfaProcedureBuilder, + name: String?, + metadata: MetaData, + ): XcfaLocation { + if (name == null) return getAnonymousLoc(builder, metadata = metadata) + locationLut.putIfAbsent(name, XcfaLocation(name, metadata = metadata)) + val location = locationLut[name] + builder.addLoc(checkNotNull(location)) + return location + } - fun buildXcfa(cProgram: CProgram): XcfaBuilder { - val builder = XcfaBuilder(cProgram.id ?: "") - val initStmtList: MutableList = ArrayList() - for (globalDeclaration in cProgram.globalDeclarations) { - val type = CComplexType.getType(globalDeclaration.get2().ref, parseContext) - if (type is CVoid) { - continue - } - if (type is CStruct) { - uniqueWarningLogger.write( - Logger.Level.INFO, "Not handling init expression of struct array ${globalDeclaration.get1()}" - ) - } - builder.addVar(XcfaGlobalVar(globalDeclaration.get2(), type.nullValue)) - if (type is CArray) { - initStmtList.add(StmtLabel( - Stmts.Assign(cast(globalDeclaration.get2(), globalDeclaration.get2().type), - cast(type.getValue("$ptrCnt"), globalDeclaration.get2().type)) - )) - } else { - if (globalDeclaration.get1().initExpr != null && globalDeclaration.get1().initExpr.expression !is UnsupportedInitializer) { - initStmtList.add(StmtLabel( - Stmts.Assign(cast(globalDeclaration.get2(), globalDeclaration.get2().type), - cast(type.castTo(globalDeclaration.get1().initExpr.expression), - globalDeclaration.get2().type)) - )) - } else { - initStmtList.add(StmtLabel( - Stmts.Assign(cast(globalDeclaration.get2(), globalDeclaration.get2().type), - cast(type.nullValue, globalDeclaration.get2().type)) - )) - } - } - - if (globalDeclaration.get1().arrayDimensions.size == 1) { - val bounds = ExprUtils.simplify(CComplexType.getUnsignedLong(parseContext) - .castTo(globalDeclaration.get1().arrayDimensions[0].expression)) - checkState(bounds is IntLitExpr || bounds is BvLitExpr, - "Only IntLit and BvLit expression expected here.") - val literalValue = if (bounds is IntLitExpr) bounds.value.toLong() else BvUtils.neutralBvLitExprToBigInteger( - bounds as BvLitExpr).toLong() - val literalToExpr = { x: Long -> - if (bounds is IntLitExpr) IntLitExpr.of( - BigInteger.valueOf(x)) else BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.valueOf(x), - (bounds as BvLitExpr).type.size) - } - val initExprs: Map> = (globalDeclaration.get1()?.initExpr as? CInitializerList)?.statements?.mapIndexed { i, it -> - Pair(i, it.get2().expression) - }?.toMap() ?: emptyMap() - for (i in 0 until literalValue) { - checkState(globalDeclaration.get1().actualType is CArray, "Only arrays are expected here") - val embeddedType = (globalDeclaration.get1().actualType as CArray).embeddedType - initStmtList.add(StmtLabel( - Stmts.MemoryAssign( - Dereference(globalDeclaration.get2().ref, literalToExpr(i), embeddedType.smtType), - cast(initExprs[i.toInt()]?.let { embeddedType.castTo(it) } ?: embeddedType.nullValue, - embeddedType.smtType)) - )) - } - } else if (globalDeclaration.get1().arrayDimensions.size > 1) { - error("Not handling init expression of high dimsension array ${globalDeclaration.get1()}") - } - } - for (function in cProgram.functions) { - val toAdd: XcfaProcedureBuilder = handleFunction(function, initStmtList, builder) - if (toAdd.name.equals("main")) builder.addEntryPoint(toAdd, listOf()) - } - return builder - } + private fun getAnonymousLoc(builder: XcfaProcedureBuilder, metadata: MetaData): XcfaLocation { + return getLoc(builder, "__loc_" + XcfaLocation.uniqueCounter(), metadata) + } - private fun handleFunction(function: CFunction, param: List, - xcfaBuilder: XcfaBuilder): XcfaProcedureBuilder { - locationLut.clear() - val flatVariables = function.flatVariables - val funcDecl = function.funcDecl - val compound = function.compound - val builder = XcfaProcedureBuilder(funcDecl.name, CPasses(checkOverflow, parseContext, uniqueWarningLogger)) - xcfaBuilder.addProcedure(builder) - val initStmtList = ArrayList() - if (param.size > 0 && builder.name.equals("main")) { - initStmtList.addAll(param) - } -// builder.setRetType(if (funcDecl.actualType is CVoid) null else funcDecl.actualType.smtType) TODO: we never need the ret type, do we? - if (funcDecl.actualType !is CVoid) { - val toAdd: VarDecl<*> = Decls.Var(funcDecl.name + "_ret", funcDecl.actualType.smtType) - parseContext.metadata.create(toAdd.ref, "cType", funcDecl.actualType) - builder.addParam(toAdd, ParamDirection.OUT) + private fun getMetadata(source: CStatement): CMetaData = + CMetaData( + lineNumberStart = source.lineNumberStart.takeIf { it != -1 }, + lineNumberStop = source.lineNumberStop.takeIf { it != -1 }, + colNumberStart = source.colNumberStart.takeIf { it != -1 }, + colNumberStop = source.colNumberStop.takeIf { it != -1 }, + offsetStart = source.offsetStart.takeIf { it != -1 }, + offsetEnd = source.offsetEnd.takeIf { it != -1 }, + sourceText = source.sourceText, + ) + + fun buildXcfa(cProgram: CProgram): XcfaBuilder { + val builder = XcfaBuilder(cProgram.id ?: "") + val initStmtList: MutableList = ArrayList() + for (globalDeclaration in cProgram.globalDeclarations) { + val type = CComplexType.getType(globalDeclaration.get2().ref, parseContext) + if (type is CVoid) { + continue + } + if (type is CStruct) { + uniqueWarningLogger.write( + Logger.Level.INFO, + "Not handling init expression of struct array ${globalDeclaration.get1()}", + ) + } + builder.addVar(XcfaGlobalVar(globalDeclaration.get2(), type.nullValue)) + if (type is CArray) { + initStmtList.add( + StmtLabel( + Stmts.Assign( + cast(globalDeclaration.get2(), globalDeclaration.get2().type), + cast(type.getValue("$ptrCnt"), globalDeclaration.get2().type), + ) + ) + ) + } else { + if ( + globalDeclaration.get1().initExpr != null && + globalDeclaration.get1().initExpr.expression !is UnsupportedInitializer + ) { + initStmtList.add( + StmtLabel( + Stmts.Assign( + cast(globalDeclaration.get2(), globalDeclaration.get2().type), + cast( + type.castTo(globalDeclaration.get1().initExpr.expression), + globalDeclaration.get2().type, + ), + ) + ) + ) } else { - // TODO we assume later that there is always a ret var, but this should change - val toAdd: VarDecl<*> = Decls.Var(funcDecl.name + "_ret", funcDecl.actualType.smtType) - val signedIntType = CSimpleTypeFactory.NamedType("int", parseContext, uniqueWarningLogger) - signedIntType.setSigned(true) - parseContext.metadata.create(toAdd.ref, "cType", signedIntType) - builder.addParam(toAdd, ParamDirection.OUT) - } - for (functionParam in funcDecl.functionParams) { - Preconditions.checkState( - functionParam.actualType is CVoid || functionParam.varDecls.size > 0, - "Function param should have an associated variable!") - for (varDecl in functionParam.varDecls) { - if (varDecl != null) builder.addParam(varDecl, ParamDirection.IN) - } + initStmtList.add( + StmtLabel( + Stmts.Assign( + cast(globalDeclaration.get2(), globalDeclaration.get2().type), + cast(type.nullValue, globalDeclaration.get2().type), + ) + ) + ) } + } - for (flatVariable in flatVariables) { - builder.addVar(flatVariable) - val type = CComplexType.getType(flatVariable.ref, parseContext) - if ((type is CArray || type is CStruct) && builder.getParams().none { it.first == flatVariable }) { - initStmtList.add(StmtLabel( - Stmts.Assign(cast(flatVariable, flatVariable.type), - cast(type.getValue("$ptrCnt"), flatVariable.type)) - )) - } + if (globalDeclaration.get1().arrayDimensions.size == 1) { + val bounds = + ExprUtils.simplify( + CComplexType.getUnsignedLong(parseContext) + .castTo(globalDeclaration.get1().arrayDimensions[0].expression) + ) + checkState( + bounds is IntLitExpr || bounds is BvLitExpr, + "Only IntLit and BvLit expression expected here.", + ) + val literalValue = + if (bounds is IntLitExpr) bounds.value.toLong() + else BvUtils.neutralBvLitExprToBigInteger(bounds as BvLitExpr).toLong() + val literalToExpr = { x: Long -> + if (bounds is IntLitExpr) IntLitExpr.of(BigInteger.valueOf(x)) + else + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.valueOf(x), + (bounds as BvLitExpr).type.size, + ) } - builder.createInitLoc(getMetadata(function)) - var init = builder.initLoc - - for (flatVariable in flatVariables) { - val type = CComplexType.getType(flatVariable.ref, parseContext) - if (type is CArray && type.embeddedType is CArray) { - // some day this is where initialization will occur. But this is not today. - error("Not handling init expression of high dimsension array $flatVariable") - } + val initExprs: Map> = + (globalDeclaration.get1()?.initExpr as? CInitializerList) + ?.statements + ?.mapIndexed { i, it -> Pair(i, it.get2().expression) } + ?.toMap() ?: emptyMap() + for (i in 0 until literalValue) { + checkState(globalDeclaration.get1().actualType is CArray, "Only arrays are expected here") + val embeddedType = (globalDeclaration.get1().actualType as CArray).embeddedType + initStmtList.add( + StmtLabel( + Stmts.MemoryAssign( + Dereference(globalDeclaration.get2().ref, literalToExpr(i), embeddedType.smtType), + cast( + initExprs[i.toInt()]?.let { embeddedType.castTo(it) } ?: embeddedType.nullValue, + embeddedType.smtType, + ), + ) + ) + ) } - - val endinit = getAnonymousLoc(builder, getMetadata(function)) - builder.addLoc(endinit) - val initEdge = XcfaEdge(init, endinit, SequenceLabel(initStmtList), - metadata = getMetadata(function)) - builder.addEdge(initEdge) - init = endinit - builder.createFinalLoc(getMetadata(function)) - val ret = builder.finalLoc.get() - builder.addLoc(ret) - val end = compound.accept(this, ParamPack(builder, init, null, null, ret)) - val edge = XcfaEdge(end, ret, metadata = getMetadata(function)) - builder.addEdge(edge) - return builder + } else if (globalDeclaration.get1().arrayDimensions.size > 1) { + error("Not handling init expression of high dimsension array ${globalDeclaration.get1()}") + } } + for (function in cProgram.functions) { + val toAdd: XcfaProcedureBuilder = handleFunction(function, initStmtList, builder) + if (toAdd.name.equals("main")) builder.addEntryPoint(toAdd, listOf()) + } + return builder + } - override fun visit(statement: CAssignment, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val lValue = statement.getlValue() - val rValue = statement.getrValue() - var initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - var xcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(location) - initLoc = rValue.accept(this, ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) - val rExpression = statement.getrExpression() - val label: StmtLabel = when (lValue) { - is Dereference<*, *, *> -> { - val op = cast(lValue.array, lValue.array.type) - val offset = cast(lValue.offset, op.type) - val castRExpression = CComplexType.getType(lValue, parseContext).castTo(rExpression) - val type = CComplexType.getType(castRExpression, parseContext) - - val deref = Dereference(op, offset, type.smtType) - - val memassign = MemoryAssignStmt.create(deref, castRExpression) - - parseContext.metadata.create(deref, "cType", CPointer(null, type, parseContext)) - StmtLabel(memassign, metadata = getMetadata(statement)) - } - - is RefExpr<*> -> { - StmtLabel(Stmts.Assign( - cast(lValue.decl as VarDecl<*>, (lValue.decl as VarDecl<*>).type), - cast(CComplexType.getType(lValue, parseContext).castTo(rExpression), lValue.type)), - metadata = getMetadata(statement)) - } - - else -> { - error("Could not handle left-hand side of assignment $statement") - } - } - - val lhs = (label.stmt as? AssignStmt<*>)?.varDecl - val type = lhs?.let { CComplexType.getType(it.ref, parseContext) } - - if (!checkOverflow || type == null || type !is CInteger || !type.isSsigned) { - xcfaEdge = XcfaEdge(initLoc, location, label, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } else { - lhs!! - val middleLoc1 = getAnonymousLoc(builder, getMetadata(statement)) - val middleLoc2 = getAnonymousLoc(builder, getMetadata(statement)) - xcfaEdge = XcfaEdge(initLoc, middleLoc1, label, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - - xcfaEdge = XcfaEdge(middleLoc1, location, - StmtLabel(type.limit(lhs.ref), metadata = getMetadata(statement)), - metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - xcfaEdge = XcfaEdge(middleLoc1, middleLoc2, - StmtLabel(Assume(Not(type.limit(lhs.ref).cond)), metadata = getMetadata(statement)), - metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - xcfaEdge = XcfaEdge(middleLoc2, location, - InvokeLabel("overflow", listOf(), metadata = getMetadata(statement)), - metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - return location + private fun handleFunction( + function: CFunction, + param: List, + xcfaBuilder: XcfaBuilder, + ): XcfaProcedureBuilder { + locationLut.clear() + val flatVariables = function.flatVariables + val funcDecl = function.funcDecl + val compound = function.compound + val builder = + XcfaProcedureBuilder(funcDecl.name, CPasses(checkOverflow, parseContext, uniqueWarningLogger)) + xcfaBuilder.addProcedure(builder) + val initStmtList = ArrayList() + if (param.size > 0 && builder.name.equals("main")) { + initStmtList.addAll(param) + } + // builder.setRetType(if (funcDecl.actualType is CVoid) null else + // funcDecl.actualType.smtType) TODO: we never need the ret type, do we? + if (funcDecl.actualType !is CVoid) { + val toAdd: VarDecl<*> = Decls.Var(funcDecl.name + "_ret", funcDecl.actualType.smtType) + parseContext.metadata.create(toAdd.ref, "cType", funcDecl.actualType) + builder.addParam(toAdd, ParamDirection.OUT) + } else { + // TODO we assume later that there is always a ret var, but this should change + val toAdd: VarDecl<*> = Decls.Var(funcDecl.name + "_ret", funcDecl.actualType.smtType) + val signedIntType = CSimpleTypeFactory.NamedType("int", parseContext, uniqueWarningLogger) + signedIntType.setSigned(true) + parseContext.metadata.create(toAdd.ref, "cType", signedIntType) + builder.addParam(toAdd, ParamDirection.OUT) + } + for (functionParam in funcDecl.functionParams) { + Preconditions.checkState( + functionParam.actualType is CVoid || functionParam.varDecls.size > 0, + "Function param should have an associated variable!", + ) + for (varDecl in functionParam.varDecls) { + if (varDecl != null) builder.addParam(varDecl, ParamDirection.IN) + } } - override fun visit(statement: CAssume, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(location) - xcfaEdge = XcfaEdge(initLoc, location, StmtLabel( - statement.assumeStmt, - choiceType = ChoiceType.MAIN_PATH, - metadata = getMetadata(statement) - ), metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - return location + for (flatVariable in flatVariables) { + builder.addVar(flatVariable) + val type = CComplexType.getType(flatVariable.ref, parseContext) + if ( + (type is CArray || type is CStruct) && builder.getParams().none { it.first == flatVariable } + ) { + initStmtList.add( + StmtLabel( + Stmts.Assign( + cast(flatVariable, flatVariable.type), + cast(type.getValue("$ptrCnt"), flatVariable.type), + ) + ) + ) + } } + builder.createInitLoc(getMetadata(function)) + var init = builder.initLoc - override fun visit(statement: CBreak, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(edge) - check(breakLoc != null) - edge = XcfaEdge(initLoc, breakLoc, metadata = getMetadata(statement)) - val unreachableLoc = XcfaLocation("Unreachable" + XcfaLocation.uniqueCounter(), - metadata = getMetadata(statement)) - builder.addLoc(unreachableLoc) - builder.addEdge(edge) - return unreachableLoc + for (flatVariable in flatVariables) { + val type = CComplexType.getType(flatVariable.ref, parseContext) + if (type is CArray && type.embeddedType is CArray) { + // some day this is where initialization will occur. But this is not today. + error("Not handling init expression of high dimsension array $flatVariable") + } } - override fun visit(statement: CCall, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val ret = statement.ret - val myParams = statement.params - var initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(location) - val params: MutableList> = ArrayList() - builder.addVar(ret) - params.add(ret.ref) - for (cStatement in myParams) { - initLoc = cStatement.accept(this, - ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) + val endinit = getAnonymousLoc(builder, getMetadata(function)) + builder.addLoc(endinit) + val initEdge = + XcfaEdge(init, endinit, SequenceLabel(initStmtList), metadata = getMetadata(function)) + builder.addEdge(initEdge) + init = endinit + builder.createFinalLoc(getMetadata(function)) + val ret = builder.finalLoc.get() + builder.addLoc(ret) + val end = compound.accept(this, ParamPack(builder, init, null, null, ret)) + val edge = XcfaEdge(end, ret, metadata = getMetadata(function)) + builder.addEdge(edge) + return builder + } + + override fun visit(statement: CAssignment, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val lValue = statement.getlValue() + val rValue = statement.getrValue() + var initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var xcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(location) + initLoc = rValue.accept(this, ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) + val rExpression = statement.getrExpression() + val label: StmtLabel = + when (lValue) { + is Dereference<*, *, *> -> { + val op = cast(lValue.array, lValue.array.type) + val offset = cast(lValue.offset, op.type) + val castRExpression = CComplexType.getType(lValue, parseContext).castTo(rExpression) + val type = CComplexType.getType(castRExpression, parseContext) + + val deref = Dereference(op, offset, type.smtType) + + val memassign = MemoryAssignStmt.create(deref, castRExpression) + + parseContext.metadata.create(deref, "cType", CPointer(null, type, parseContext)) + StmtLabel(memassign, metadata = getMetadata(statement)) } - params.addAll(myParams.stream().map { obj: CStatement -> obj.expression } - .collect(Collectors.toList())) - val call = InvokeLabel(statement.functionId, params, metadata = getMetadata(statement)) - xcfaEdge = XcfaEdge(initLoc, location, call, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - return location - } - override fun visit(statement: CCase, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - return statement.statement.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - } + is RefExpr<*> -> { + StmtLabel( + Stmts.Assign( + cast(lValue.decl as VarDecl<*>, (lValue.decl as VarDecl<*>).type), + cast(CComplexType.getType(lValue, parseContext).castTo(rExpression), lValue.type), + ), + metadata = getMetadata(statement), + ) + } - override fun visit(statement: CCompound, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - var lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val preStatements = statement.preStatements - val postStatements = statement.postStatements - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - val edge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(edge) - lastLoc = initLoc - if (preStatements != null) lastLoc = preStatements.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - for (cStatement in statement.getcStatementList()) { - if (cStatement != null) lastLoc = cStatement.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + else -> { + error("Could not handle left-hand side of assignment $statement") } - if (postStatements != null) lastLoc = postStatements.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - return lastLoc - } + } - override fun visit(statement: CContinue, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(edge) - check(continueLoc != null) - edge = XcfaEdge(initLoc, continueLoc, metadata = getMetadata(statement)) - val unreachableLoc: XcfaLocation = XcfaLocation( - "Unreachable" + XcfaLocation.uniqueCounter(), metadata = getMetadata(statement)) - builder.addLoc(unreachableLoc) - builder.addEdge(edge) - return unreachableLoc - } + val lhs = (label.stmt as? AssignStmt<*>)?.varDecl + val type = lhs?.let { CComplexType.getType(it.ref, parseContext) } - override fun visit(statement: CDefault, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - return statement.statement.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + if (!checkOverflow || type == null || type !is CInteger || !type.isSsigned) { + xcfaEdge = XcfaEdge(initLoc, location, label, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + } else { + lhs!! + val middleLoc1 = getAnonymousLoc(builder, getMetadata(statement)) + val middleLoc2 = getAnonymousLoc(builder, getMetadata(statement)) + xcfaEdge = XcfaEdge(initLoc, middleLoc1, label, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + + xcfaEdge = + XcfaEdge( + middleLoc1, + location, + StmtLabel(type.limit(lhs.ref), metadata = getMetadata(statement)), + metadata = getMetadata(statement), + ) + builder.addEdge(xcfaEdge) + xcfaEdge = + XcfaEdge( + middleLoc1, + middleLoc2, + StmtLabel(Assume(Not(type.limit(lhs.ref).cond)), metadata = getMetadata(statement)), + metadata = getMetadata(statement), + ) + builder.addEdge(xcfaEdge) + xcfaEdge = + XcfaEdge( + middleLoc2, + location, + InvokeLabel("overflow", listOf(), metadata = getMetadata(statement)), + metadata = getMetadata(statement), + ) + builder.addEdge(xcfaEdge) } + return location + } - override fun visit(statement: CDoWhile, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val body = statement.body - val guard = statement.guard - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val innerEndLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val innerInnerGuard = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val outerInnerGuard = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(endLoc) - builder.addLoc(innerInnerGuard) - builder.addLoc(outerInnerGuard) - builder.addLoc(innerEndLoc) - builder.addLoc(initLoc) - var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val lastBody = body.accept(this, - ParamPack(builder, initLoc, endLoc, innerEndLoc, returnLoc)) - xcfaEdge = XcfaEdge(lastBody, innerEndLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val lastPre = buildWithoutPostStatement(guard, - ParamPack(builder, innerEndLoc, null, null, returnLoc)) - val assume = StmtLabel(Stmts.Assume( - AbstractExprs.Neq(guard.expression, CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.MAIN_PATH, metadata = getMetadata(guard)) - xcfaEdge = XcfaEdge(lastPre, innerInnerGuard, assume, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val assume1 = StmtLabel(Stmts.Assume( - AbstractExprs.Eq(guard.expression, CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.ALTERNATIVE_PATH, metadata = getMetadata(guard)) - xcfaEdge = XcfaEdge(lastPre, outerInnerGuard, assume1, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val outerLastGuard = buildPostStatement(guard, - ParamPack(builder, outerInnerGuard, null, null, null)) - val innerLastGuard = buildPostStatement(guard, - ParamPack(builder, innerInnerGuard, null, null, null)) - xcfaEdge = XcfaEdge(outerLastGuard, endLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - xcfaEdge = XcfaEdge(innerLastGuard, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - return endLoc + override fun visit(statement: CAssume, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(location) + xcfaEdge = + XcfaEdge( + initLoc, + location, + StmtLabel( + statement.assumeStmt, + choiceType = ChoiceType.MAIN_PATH, + metadata = getMetadata(statement), + ), + metadata = getMetadata(statement), + ) + builder.addEdge(xcfaEdge) + return location + } + + override fun visit(statement: CBreak, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(edge) + check(breakLoc != null) + edge = XcfaEdge(initLoc, breakLoc, metadata = getMetadata(statement)) + val unreachableLoc = + XcfaLocation("Unreachable" + XcfaLocation.uniqueCounter(), metadata = getMetadata(statement)) + builder.addLoc(unreachableLoc) + builder.addEdge(edge) + return unreachableLoc + } + + override fun visit(statement: CCall, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val ret = statement.ret + val myParams = statement.params + var initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(location) + val params: MutableList> = ArrayList() + builder.addVar(ret) + params.add(ret.ref) + for (cStatement in myParams) { + initLoc = + cStatement.accept(this, ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) } + params.addAll( + myParams.stream().map { obj: CStatement -> obj.expression }.collect(Collectors.toList()) + ) + val call = InvokeLabel(statement.functionId, params, metadata = getMetadata(statement)) + xcfaEdge = XcfaEdge(initLoc, location, call, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + return location + } + + override fun visit(statement: CCase, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + return statement.statement.accept( + this, + ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc), + ) + } - override fun visit(statement: CExpr, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - return lastLoc + override fun visit(statement: CCompound, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + var lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val preStatements = statement.preStatements + val postStatements = statement.postStatements + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + val edge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(edge) + lastLoc = initLoc + if (preStatements != null) + lastLoc = + preStatements.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + for (cStatement in statement.getcStatementList()) { + if (cStatement != null) + lastLoc = + cStatement.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) } + if (postStatements != null) + lastLoc = + postStatements.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + return lastLoc + } - override fun visit(statement: CFor, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val increment = statement.increment - val init = statement.init - val guard = statement.guard - val body = statement.body - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val endInit = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val startIncrement = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val outerLastTest = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(endLoc) - builder.addLoc(outerLastTest) - builder.addLoc(endInit) - builder.addLoc(initLoc) - builder.addLoc(startIncrement) - var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val lastInit = if (init == null) initLoc else init.accept(this, - ParamPack(builder, initLoc, null, null, returnLoc)) - val lastTest = if (guard == null) lastInit else buildWithoutPostStatement(guard, - ParamPack(builder, lastInit!!, null, null, returnLoc)) - val assume = StmtLabel( - Stmts.Assume(if (guard == null) True() else AbstractExprs.Neq(guard.expression, - CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.MAIN_PATH, - metadata = if (guard == null) getMetadata(statement) else getMetadata(guard) + override fun visit(statement: CContinue, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(edge) + check(continueLoc != null) + edge = XcfaEdge(initLoc, continueLoc, metadata = getMetadata(statement)) + val unreachableLoc: XcfaLocation = + XcfaLocation("Unreachable" + XcfaLocation.uniqueCounter(), metadata = getMetadata(statement)) + builder.addLoc(unreachableLoc) + builder.addEdge(edge) + return unreachableLoc + } + + override fun visit(statement: CDefault, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + return statement.statement.accept( + this, + ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc), + ) + } + + override fun visit(statement: CDoWhile, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val body = statement.body + val guard = statement.guard + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val innerEndLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val innerInnerGuard = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val outerInnerGuard = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(endLoc) + builder.addLoc(innerInnerGuard) + builder.addLoc(outerInnerGuard) + builder.addLoc(innerEndLoc) + builder.addLoc(initLoc) + var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val lastBody = body.accept(this, ParamPack(builder, initLoc, endLoc, innerEndLoc, returnLoc)) + xcfaEdge = XcfaEdge(lastBody, innerEndLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val lastPre = + buildWithoutPostStatement(guard, ParamPack(builder, innerEndLoc, null, null, returnLoc)) + val assume = + StmtLabel( + Stmts.Assume( + AbstractExprs.Neq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, + ) + ), + choiceType = ChoiceType.MAIN_PATH, + metadata = getMetadata(guard), + ) + xcfaEdge = XcfaEdge(lastPre, innerInnerGuard, assume, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val assume1 = + StmtLabel( + Stmts.Assume( + AbstractExprs.Eq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, + ) + ), + choiceType = ChoiceType.ALTERNATIVE_PATH, + metadata = getMetadata(guard), + ) + xcfaEdge = XcfaEdge(lastPre, outerInnerGuard, assume1, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val outerLastGuard = + buildPostStatement(guard, ParamPack(builder, outerInnerGuard, null, null, null)) + val innerLastGuard = + buildPostStatement(guard, ParamPack(builder, innerInnerGuard, null, null, null)) + xcfaEdge = XcfaEdge(outerLastGuard, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + xcfaEdge = XcfaEdge(innerLastGuard, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + return endLoc + } + + override fun visit(statement: CExpr, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + return lastLoc + } + + override fun visit(statement: CFor, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val increment = statement.increment + val init = statement.init + val guard = statement.guard + val body = statement.body + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val endInit = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val startIncrement = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val outerLastTest = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(endLoc) + builder.addLoc(outerLastTest) + builder.addLoc(endInit) + builder.addLoc(initLoc) + builder.addLoc(startIncrement) + var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val lastInit = + if (init == null) initLoc + else init.accept(this, ParamPack(builder, initLoc, null, null, returnLoc)) + val lastTest = + if (guard == null) lastInit + else buildWithoutPostStatement(guard, ParamPack(builder, lastInit!!, null, null, returnLoc)) + val assume = + StmtLabel( + Stmts.Assume( + if (guard == null) True() + else + AbstractExprs.Neq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, + ) + ), + choiceType = ChoiceType.MAIN_PATH, + metadata = if (guard == null) getMetadata(statement) else getMetadata(guard), + ) + check(lastTest != null) + xcfaEdge = XcfaEdge(lastTest, endInit, assume, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val assume1 = + StmtLabel( + Stmts.Assume( + if (guard == null) False() + else + AbstractExprs.Eq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, + ) + ), + choiceType = ChoiceType.ALTERNATIVE_PATH, + metadata = if (guard == null) getMetadata(statement) else getMetadata(guard), + ) + xcfaEdge = XcfaEdge(lastTest, outerLastTest, assume1, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val innerLastGuard = + if (guard == null) endInit + else buildPostStatement(guard, ParamPack(builder, endInit, endLoc, startIncrement, returnLoc)) + val lastBody = + if (body == null) innerLastGuard + else body.accept(this, ParamPack(builder, innerLastGuard, endLoc, startIncrement, returnLoc)) + xcfaEdge = XcfaEdge(lastBody, startIncrement, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + if (increment != null) { + val lastIncrement = + increment.accept(this, ParamPack(builder, startIncrement, null, null, returnLoc)) + xcfaEdge = XcfaEdge(lastIncrement, lastInit, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + } else { + xcfaEdge = XcfaEdge(startIncrement, lastInit, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + } + val outerLastGuard = + if (guard == null) outerLastTest + else + buildPostStatement( + guard, + ParamPack(builder, outerLastTest, endLoc, startIncrement, returnLoc), ) - check(lastTest != null) - xcfaEdge = XcfaEdge(lastTest, endInit, assume, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val assume1 = StmtLabel( - Stmts.Assume(if (guard == null) False() else AbstractExprs.Eq(guard.expression, - CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.ALTERNATIVE_PATH, - metadata = if (guard == null) getMetadata(statement) else getMetadata(guard) + xcfaEdge = XcfaEdge(outerLastGuard, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + return endLoc + } + + override fun visit(statement: CGoto, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(edge) + edge = + XcfaEdge( + initLoc, + getLoc(builder, statement.label, metadata = getMetadata(statement)), + metadata = getMetadata(statement), + ) + builder.addLoc(getLoc(builder, statement.label, metadata = getMetadata(statement))) + val unreachableLoc: XcfaLocation = + XcfaLocation("Unreachable" + XcfaLocation.uniqueCounter(), metadata = getMetadata(statement)) + builder.addLoc(unreachableLoc) + builder.addEdge(edge) + return unreachableLoc + } + + override fun visit(statement: CIf, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val elseStatement = statement.elseStatement + val body = statement.body + val guard = statement.guard + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val mainBranch = getAnonymousLoc(builder, metadata = getMetadata(statement)) + val elseBranch = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(endLoc) + builder.addLoc(mainBranch) + builder.addLoc(elseBranch) + builder.addLoc(initLoc) + var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val endGuard = + buildWithoutPostStatement( + guard, + ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc), + ) + val assume = + StmtLabel( + Stmts.Assume( + AbstractExprs.Neq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, + ) + ), + choiceType = ChoiceType.MAIN_PATH, + metadata = getMetadata(guard), + ) + xcfaEdge = XcfaEdge(endGuard, mainBranch, assume, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val assume1 = + StmtLabel( + Stmts.Assume( + AbstractExprs.Eq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, + ) + ), + choiceType = ChoiceType.ALTERNATIVE_PATH, + metadata = getMetadata(guard), + ) + xcfaEdge = XcfaEdge(endGuard, elseBranch, assume1, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val mainAfterGuard = + buildPostStatement(guard, ParamPack(builder, mainBranch, breakLoc, continueLoc, returnLoc)) + val mainEnd = + body.accept(this, ParamPack(builder, mainAfterGuard, breakLoc, continueLoc, returnLoc)) + if (elseStatement != null) { + val elseAfterGuard = + buildPostStatement(guard, ParamPack(builder, elseBranch, breakLoc, continueLoc, returnLoc)) + val elseEnd = + elseStatement.accept( + this, + ParamPack(builder, elseAfterGuard, breakLoc, continueLoc, returnLoc), ) - xcfaEdge = XcfaEdge(lastTest, outerLastTest, assume1, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val innerLastGuard = if (guard == null) endInit else buildPostStatement(guard, - ParamPack(builder, endInit, endLoc, startIncrement, returnLoc)) - val lastBody = if (body == null) innerLastGuard else body.accept(this, - ParamPack(builder, innerLastGuard, endLoc, startIncrement, returnLoc)) - xcfaEdge = XcfaEdge(lastBody, startIncrement, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - if (increment != null) { - val lastIncrement = increment.accept(this, - ParamPack(builder, startIncrement, null, null, returnLoc)) - xcfaEdge = XcfaEdge(lastIncrement, lastInit, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } else { - xcfaEdge = XcfaEdge(startIncrement, lastInit, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - val outerLastGuard = if (guard == null) outerLastTest else buildPostStatement(guard, - ParamPack(builder, outerLastTest, endLoc, startIncrement, returnLoc)) - xcfaEdge = XcfaEdge(outerLastGuard, endLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - return endLoc + xcfaEdge = XcfaEdge(elseEnd, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + } else { + xcfaEdge = XcfaEdge(elseBranch, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) } + xcfaEdge = XcfaEdge(mainEnd, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + return endLoc + } - override fun visit(statement: CGoto, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - var edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(edge) - edge = XcfaEdge(initLoc, - getLoc(builder, statement.label, metadata = getMetadata(statement)), - metadata = getMetadata(statement) - ) - builder.addLoc(getLoc(builder, statement.label, metadata = getMetadata(statement))) - val unreachableLoc: XcfaLocation = XcfaLocation( - "Unreachable" + XcfaLocation.uniqueCounter(), metadata = getMetadata(statement)) - builder.addLoc(unreachableLoc) - builder.addEdge(edge) - return unreachableLoc + override fun visit(statement: CInitializerList, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + var lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + for (cStatement in statement.statements) { + lastLoc = + cStatement + .get2() + .accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) } + return lastLoc + } - override fun visit(statement: CIf, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val elseStatement = statement.elseStatement - val body = statement.body - val guard = statement.guard - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val mainBranch = getAnonymousLoc(builder, metadata = getMetadata(statement)) - val elseBranch = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(endLoc) - builder.addLoc(mainBranch) - builder.addLoc(elseBranch) - builder.addLoc(initLoc) - var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + override fun visit(statement: CRet, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val expr = statement.expr + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + val xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val endExpr = + expr?.accept(this, ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) ?: initLoc + val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(endLoc) + val key: VarDecl<*> = builder.getParams()[0].first + check(returnLoc != null) + val type = CComplexType.getType(key.ref, parseContext) + val edge = + XcfaEdge( + endExpr, + returnLoc, + StmtLabel( + Stmts.Assign( + cast(key, key.type), + cast(type.castTo(expr?.expression ?: type.nullValue), key.type), + ), + metadata = getMetadata(statement), + ), + metadata = getMetadata(statement), + ) + builder.addEdge(edge) + return endLoc + } + + override fun visit(statement: CSwitch, param: ParamPack): XcfaLocation { + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val testValue = statement.testValue + val body = statement.body + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(endLoc) + val edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(edge) + val endInit = + buildWithoutPostStatement( + testValue, + ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc), + ) + Preconditions.checkState(body is CCompound, "Switch body has to be a CompoundStatement!") + var defaultExpr: Expr? = True() + for (cStatement in (body as CCompound).getcStatementList()) { + if (cStatement is CCase) { + defaultExpr = + BoolExprs.And( + defaultExpr, + AbstractExprs.Neq(testValue.expression, cStatement.expr.expression), + ) + } + } + var lastLocation: XcfaLocation? = null + for (cStatement in body.getcStatementList()) { + val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(location) + var xcfaEdge: XcfaEdge + if (lastLocation != null) { + xcfaEdge = XcfaEdge(lastLocation, location, metadata = getMetadata(statement)) builder.addEdge(xcfaEdge) - val endGuard = buildWithoutPostStatement(guard, - ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) - val assume = StmtLabel( - Stmts.Assume(AbstractExprs.Neq(guard.expression, - CComplexType.getType(guard.expression, parseContext).nullValue)), + } + if (cStatement is CCase) { + val afterGuard = + buildPostStatement( + testValue, + ParamPack(builder, checkNotNull(endInit), breakLoc, continueLoc, returnLoc), + ) + val assume = + StmtLabel( + Stmts.Assume(AbstractExprs.Eq(testValue.expression, cStatement.expr.expression)), choiceType = ChoiceType.MAIN_PATH, - metadata = getMetadata(guard) - ) - xcfaEdge = XcfaEdge(endGuard, mainBranch, assume, metadata = getMetadata(statement)) + metadata = getMetadata(testValue), + ) + xcfaEdge = XcfaEdge(afterGuard, location, assume, metadata = getMetadata(statement)) builder.addEdge(xcfaEdge) - val assume1 = StmtLabel( - Stmts.Assume(AbstractExprs.Eq(guard.expression, - CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.ALTERNATIVE_PATH, - metadata = getMetadata(guard) - ) - xcfaEdge = XcfaEdge(endGuard, elseBranch, assume1, metadata = getMetadata(statement)) + } else if (cStatement is CDefault) { + val afterGuard = + buildPostStatement( + testValue, + ParamPack(builder, endInit!!, breakLoc, continueLoc, returnLoc), + ) + val assume = + StmtLabel( + Stmts.Assume(defaultExpr), + choiceType = ChoiceType.MAIN_PATH, // TODO: is this what validators expect? + metadata = getMetadata(cStatement), + ) + xcfaEdge = XcfaEdge(afterGuard, location, assume, metadata = getMetadata(statement)) builder.addEdge(xcfaEdge) - val mainAfterGuard = buildPostStatement(guard, - ParamPack(builder, mainBranch, breakLoc, continueLoc, returnLoc)) - val mainEnd = body.accept(this, - ParamPack(builder, mainAfterGuard, breakLoc, continueLoc, returnLoc)) - if (elseStatement != null) { - val elseAfterGuard = buildPostStatement(guard, - ParamPack(builder, elseBranch, breakLoc, continueLoc, returnLoc)) - val elseEnd = elseStatement.accept(this, - ParamPack(builder, elseAfterGuard, breakLoc, continueLoc, returnLoc)) - xcfaEdge = XcfaEdge(elseEnd, endLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } else { - xcfaEdge = XcfaEdge(elseBranch, endLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - xcfaEdge = XcfaEdge(mainEnd, endLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - return endLoc - } - - override fun visit(statement: CInitializerList, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - var lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - for (cStatement in statement.statements) { - lastLoc = cStatement.get2() - .accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - } - return lastLoc - } - - override fun visit(statement: CRet, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val expr = statement.expr - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - val xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val endExpr = expr?.accept(this, - ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) ?: initLoc - val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(endLoc) - val key: VarDecl<*> = builder.getParams()[0].first - check(returnLoc != null) - val type = CComplexType.getType(key.ref, parseContext) - val edge = XcfaEdge(endExpr, returnLoc, StmtLabel(Stmts.Assign(cast(key, key.type), - cast(type.castTo(expr?.expression ?: type.nullValue), key.type)), - metadata = getMetadata(statement)), metadata = getMetadata(statement)) - builder.addEdge(edge) - return endLoc + } + lastLocation = + cStatement.accept(this, ParamPack(builder, location, endLoc, continueLoc, returnLoc)) } - - override fun visit(statement: CSwitch, param: ParamPack): XcfaLocation { - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val testValue = statement.testValue - val body = statement.body - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(endLoc) - val edge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(edge) - val endInit = buildWithoutPostStatement(testValue, - ParamPack(builder, initLoc, breakLoc, continueLoc, returnLoc)) - Preconditions.checkState(body is CCompound, "Switch body has to be a CompoundStatement!") - var defaultExpr: Expr? = True() - for (cStatement in (body as CCompound).getcStatementList()) { - if (cStatement is CCase) { - defaultExpr = BoolExprs.And(defaultExpr, - AbstractExprs.Neq(testValue.expression, cStatement.expr.expression)) - } - } - var lastLocation: XcfaLocation? = null - for (cStatement in body.getcStatementList()) { - val location = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(location) - var xcfaEdge: XcfaEdge - if (lastLocation != null) { - xcfaEdge = XcfaEdge(lastLocation, location, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - if (cStatement is CCase) { - val afterGuard = buildPostStatement(testValue, - ParamPack(builder, checkNotNull(endInit), breakLoc, continueLoc, returnLoc)) - val assume = StmtLabel( - Stmts.Assume( - AbstractExprs.Eq(testValue.expression, cStatement.expr.expression)), - choiceType = ChoiceType.MAIN_PATH, - metadata = getMetadata(testValue) - ) - xcfaEdge = XcfaEdge(afterGuard, location, assume, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } else if (cStatement is CDefault) { - val afterGuard = buildPostStatement(testValue, - ParamPack(builder, endInit!!, breakLoc, continueLoc, returnLoc)) - val assume = StmtLabel( - Stmts.Assume(defaultExpr), - choiceType = ChoiceType.MAIN_PATH, // TODO: is this what validators expect? - metadata = getMetadata(cStatement) - ) - xcfaEdge = XcfaEdge(afterGuard, location, assume, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - lastLocation = cStatement.accept(this, - ParamPack(builder, location, endLoc, continueLoc, returnLoc)) - } - if (lastLocation != null) { - val xcfaEdge: XcfaEdge = XcfaEdge(lastLocation, endLoc, - metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - return endLoc + if (lastLocation != null) { + val xcfaEdge: XcfaEdge = XcfaEdge(lastLocation, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) } + return endLoc + } - override fun visit(statement: CWhile, param: ParamPack): XcfaLocation { - val UNROLL_COUNT = 0 - val builder: XcfaProcedureBuilder = param.builder - val lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val guard = statement.guard - val body = statement.body - var initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + override fun visit(statement: CWhile, param: ParamPack): XcfaLocation { + val UNROLL_COUNT = 0 + val builder: XcfaProcedureBuilder = param.builder + val lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val guard = statement.guard + val body = statement.body + var initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(endLoc) + val outerBeforeGuard = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(outerBeforeGuard) + for (i in 0 until if (UNROLL_COUNT == 0) 1 else UNROLL_COUNT) { + val innerLoop = getAnonymousLoc(builder, metadata = getMetadata(statement)) + builder.addLoc(innerLoop) + val testEndLoc = + buildWithoutPostStatement(guard, ParamPack(builder, initLoc, null, null, returnLoc)) + if (UNROLL_COUNT > 0) { + initLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) builder.addLoc(initLoc) - var xcfaEdge: XcfaEdge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val endLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(endLoc) - val outerBeforeGuard = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(outerBeforeGuard) - for (i in 0 until if (UNROLL_COUNT == 0) 1 else UNROLL_COUNT) { - val innerLoop = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(innerLoop) - val testEndLoc = buildWithoutPostStatement(guard, - ParamPack(builder, initLoc, null, null, returnLoc)) - if (UNROLL_COUNT > 0) { - initLoc = getAnonymousLoc(builder, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - } - val assume = StmtLabel( - Stmts.Assume(AbstractExprs.Neq(guard.expression, - CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.MAIN_PATH, - metadata = getMetadata(guard) + } + val assume = + StmtLabel( + Stmts.Assume( + AbstractExprs.Neq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, ) - xcfaEdge = XcfaEdge(testEndLoc, innerLoop, assume, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val assume1 = StmtLabel( - Stmts.Assume(AbstractExprs.Eq(guard.expression, - CComplexType.getType(guard.expression, parseContext).nullValue)), - choiceType = ChoiceType.ALTERNATIVE_PATH, - metadata = getMetadata(statement) + ), + choiceType = ChoiceType.MAIN_PATH, + metadata = getMetadata(guard), + ) + xcfaEdge = XcfaEdge(testEndLoc, innerLoop, assume, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val assume1 = + StmtLabel( + Stmts.Assume( + AbstractExprs.Eq( + guard.expression, + CComplexType.getType(guard.expression, parseContext).nullValue, ) - xcfaEdge = XcfaEdge(testEndLoc, outerBeforeGuard, assume1, - metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - val lastGuard = buildPostStatement(guard, - ParamPack(builder, innerLoop, endLoc, initLoc, returnLoc)) - val lastBody = body.accept(this, - ParamPack(builder, lastGuard, endLoc, initLoc, returnLoc)) - xcfaEdge = XcfaEdge(lastBody, initLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - } - val outerLastGuard = buildPostStatement(guard, - ParamPack(builder, outerBeforeGuard, null, null, null)) - xcfaEdge = XcfaEdge(outerLastGuard, endLoc, metadata = getMetadata(statement)) - builder.addEdge(xcfaEdge) - return endLoc + ), + choiceType = ChoiceType.ALTERNATIVE_PATH, + metadata = getMetadata(statement), + ) + xcfaEdge = XcfaEdge(testEndLoc, outerBeforeGuard, assume1, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + val lastGuard = + buildPostStatement(guard, ParamPack(builder, innerLoop, endLoc, initLoc, returnLoc)) + val lastBody = body.accept(this, ParamPack(builder, lastGuard, endLoc, initLoc, returnLoc)) + xcfaEdge = XcfaEdge(lastBody, initLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) } + val outerLastGuard = + buildPostStatement(guard, ParamPack(builder, outerBeforeGuard, null, null, null)) + xcfaEdge = XcfaEdge(outerLastGuard, endLoc, metadata = getMetadata(statement)) + builder.addEdge(xcfaEdge) + return endLoc + } - private fun buildWithoutPostStatement(cStatement: CStatement, param: ParamPack): XcfaLocation { - Preconditions.checkState(cStatement is CCompound, - "Currently only CCompounds have pre- and post statements!") - val statement = cStatement as CCompound - val builder: XcfaProcedureBuilder = param.builder - var lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val preStatements = statement.preStatements - val postStatements = statement.postStatements - val cStatementList = statement.getcStatementList() - val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) - builder.addLoc(initLoc) - val edge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) - builder.addEdge(edge) - lastLoc = initLoc - if (preStatements != null) lastLoc = preStatements.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - for (i in 0 until cStatementList.size - 1) { - val stmt = cStatementList[i] - if (stmt != null) lastLoc = stmt.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - } - if (cStatementList.size == 0) return lastLoc - val lastStatement = cStatementList[cStatementList.size - 1] - lastLoc = if (postStatements == null) { - buildWithoutPostStatement(lastStatement, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - } else { - lastStatement.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - } - return lastLoc + private fun buildWithoutPostStatement(cStatement: CStatement, param: ParamPack): XcfaLocation { + Preconditions.checkState( + cStatement is CCompound, + "Currently only CCompounds have pre- and post statements!", + ) + val statement = cStatement as CCompound + val builder: XcfaProcedureBuilder = param.builder + var lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val preStatements = statement.preStatements + val postStatements = statement.postStatements + val cStatementList = statement.getcStatementList() + val initLoc = getLoc(builder, statement.id, metadata = getMetadata(statement)) + builder.addLoc(initLoc) + val edge = XcfaEdge(lastLoc, initLoc, metadata = getMetadata(statement)) + builder.addEdge(edge) + lastLoc = initLoc + if (preStatements != null) + lastLoc = + preStatements.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + for (i in 0 until cStatementList.size - 1) { + val stmt = cStatementList[i] + if (stmt != null) + lastLoc = stmt.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) } + if (cStatementList.size == 0) return lastLoc + val lastStatement = cStatementList[cStatementList.size - 1] + lastLoc = + if (postStatements == null) { + buildWithoutPostStatement( + lastStatement, + ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc), + ) + } else { + lastStatement.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + } + return lastLoc + } - private fun buildPostStatement(cStatement: CStatement, param: ParamPack): XcfaLocation { - Preconditions.checkState(cStatement is CCompound, - "Currently only CCompounds have pre- and post statements!") - val statement = cStatement as CCompound - val builder: XcfaProcedureBuilder = param.builder - var lastLoc = param.lastLoc - val breakLoc = param.breakLoc - val continueLoc = param.continueLoc - val returnLoc = param.returnLoc - val preStatements = statement.preStatements - val postStatements = statement.postStatements - val cStatementList = statement.getcStatementList() - lastLoc = if (postStatements != null) postStatements.accept(this, - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) else buildPostStatement( - cStatementList[cStatementList.size - 1], - ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) - return lastLoc - } + private fun buildPostStatement(cStatement: CStatement, param: ParamPack): XcfaLocation { + Preconditions.checkState( + cStatement is CCompound, + "Currently only CCompounds have pre- and post statements!", + ) + val statement = cStatement as CCompound + val builder: XcfaProcedureBuilder = param.builder + var lastLoc = param.lastLoc + val breakLoc = param.breakLoc + val continueLoc = param.continueLoc + val returnLoc = param.returnLoc + val preStatements = statement.preStatements + val postStatements = statement.postStatements + val cStatementList = statement.getcStatementList() + lastLoc = + if (postStatements != null) + postStatements.accept(this, ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc)) + else + buildPostStatement( + cStatementList[cStatementList.size - 1], + ParamPack(builder, lastLoc, breakLoc, continueLoc, returnLoc), + ) + return lastLoc + } - class ParamPack(builder: XcfaProcedureBuilder, lastLoc: XcfaLocation, breakLoc: XcfaLocation?, - continueLoc: XcfaLocation?, returnLoc: XcfaLocation?) { - - val builder: XcfaProcedureBuilder - val lastLoc: XcfaLocation - val breakLoc: XcfaLocation? - val continueLoc: XcfaLocation? - val returnLoc: XcfaLocation? - - init { - this.builder = builder - this.lastLoc = lastLoc - this.breakLoc = breakLoc - this.continueLoc = continueLoc - this.returnLoc = returnLoc - } + class ParamPack( + builder: XcfaProcedureBuilder, + lastLoc: XcfaLocation, + breakLoc: XcfaLocation?, + continueLoc: XcfaLocation?, + returnLoc: XcfaLocation?, + ) { + + val builder: XcfaProcedureBuilder + val lastLoc: XcfaLocation + val breakLoc: XcfaLocation? + val continueLoc: XcfaLocation? + val returnLoc: XcfaLocation? + + init { + this.builder = builder + this.lastLoc = lastLoc + this.breakLoc = breakLoc + this.continueLoc = continueLoc + this.returnLoc = returnLoc } -} \ No newline at end of file + } +} diff --git a/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java b/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java index c6a06d5bb8..f143194257 100644 --- a/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java +++ b/subprojects/xcfa/litmus2xcfa/src/main/java/hu/bme/mit/theta/frontend/litmus2xcfa/dsl/LitmusAArch64.java @@ -13,9 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.frontend.litmus2xcfa.dsl; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.decl.Decls.Var; +import static hu.bme.mit.theta.core.stmt.Stmts.Assign; +import static hu.bme.mit.theta.core.stmt.Stmts.Assume; +import static hu.bme.mit.theta.core.type.bvtype.BvExprs.*; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; + import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.type.Expr; @@ -26,18 +33,9 @@ import hu.bme.mit.theta.litmus2xcfa.dsl.gen.LitmusAArch64Parser; import hu.bme.mit.theta.xcfa.model.*; import hu.bme.mit.theta.xcfa.passes.LitmusPasses; - import java.math.BigInteger; import java.util.*; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.decl.Decls.Var; -import static hu.bme.mit.theta.core.stmt.Stmts.Assign; -import static hu.bme.mit.theta.core.stmt.Stmts.Assume; -import static hu.bme.mit.theta.core.type.bvtype.BvExprs.*; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; - public class LitmusAArch64 extends LitmusAArch64BaseVisitor { private final Map, Optional>>> vars; private final Map>> regLookup; @@ -68,25 +66,42 @@ public LitmusAArch64() { public XCFA visitMain(LitmusAArch64Parser.MainContext ctx) { XcfaBuilder builder = new XcfaBuilder(""); - for (final LitmusAArch64Parser.VariableDeclaratorContext variableDeclaratorContext : ctx.variableDeclaratorList().variableDeclarator()) { - final LitmusAArch64Parser.VariableDeclaratorLocationContext varDeclCtx = variableDeclaratorContext.variableDeclaratorLocation(); - final LitmusAArch64Parser.VariableDeclaratorRegisterLocationContext regDeclCtx = variableDeclaratorContext.variableDeclaratorRegisterLocation(); + for (final LitmusAArch64Parser.VariableDeclaratorContext variableDeclaratorContext : + ctx.variableDeclaratorList().variableDeclarator()) { + final LitmusAArch64Parser.VariableDeclaratorLocationContext varDeclCtx = + variableDeclaratorContext.variableDeclaratorLocation(); + final LitmusAArch64Parser.VariableDeclaratorRegisterLocationContext regDeclCtx = + variableDeclaratorContext.variableDeclaratorRegisterLocation(); if (varDeclCtx != null) { - getGlobalFromName(varDeclCtx.location().getText(), BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger(varDeclCtx.constant().getText()), 64), builder); + getGlobalFromName( + varDeclCtx.location().getText(), + BvUtils.bigIntegerToNeutralBvLitExpr( + new BigInteger(varDeclCtx.constant().getText()), 64), + builder); } else if (regDeclCtx != null && regDeclCtx.Amp() == null) { final int id = regDeclCtx.threadId().id; globalAddresses.putIfAbsent(id, new LinkedHashMap<>()); - globalAddresses.get(id).put(regDeclCtx.register64().getText(), getGlobalFromName(regDeclCtx.location().getText(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 64), builder)); + globalAddresses + .get(id) + .put( + regDeclCtx.register64().getText(), + getGlobalFromName( + regDeclCtx.location().getText(), + BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 64), + builder)); } else { - throw new UnsupportedOperationException("Only registers storing addresses of global variables are supported!"); + throw new UnsupportedOperationException( + "Only registers storing addresses of global variables are supported!"); } } - for (final LitmusAArch64Parser.ThreadIdContext threadIdContext : ctx.program().threadDeclaratorList().threadId()) { + for (final LitmusAArch64Parser.ThreadIdContext threadIdContext : + ctx.program().threadDeclaratorList().threadId()) { final int id = threadIdContext.id; regLookup.putIfAbsent(id, new LinkedHashMap<>()); globalAddresses.putIfAbsent(id, new LinkedHashMap<>()); locations.putIfAbsent(id, new LinkedHashMap<>()); - final XcfaProcedureBuilder procedure = new XcfaProcedureBuilder("thrd" + id, new LitmusPasses()); + final XcfaProcedureBuilder procedure = + new XcfaProcedureBuilder("thrd" + id, new LitmusPasses()); builder.addProcedure(procedure); builder.addEntryPoint(procedure, List.of()); procedure.createInitLoc(); @@ -94,10 +109,13 @@ public XCFA visitMain(LitmusAArch64Parser.MainContext ctx) { lastLocation.put(id, procedure.getInitLoc()); threadIds.add(id); } - for (LitmusAArch64Parser.InstructionRowContext instructionRowContext : ctx.program().instructionList().instructionRow()) { - List instruction = instructionRowContext.instruction(); + for (LitmusAArch64Parser.InstructionRowContext instructionRowContext : + ctx.program().instructionList().instructionRow()) { + List instruction = + instructionRowContext.instruction(); for (int i = 0; i < instruction.size(); i++) { - final LitmusAArch64Parser.InstructionContext instructionContext = instruction.get(i); + final LitmusAArch64Parser.InstructionContext instructionContext = + instruction.get(i); currentProc = threadIds.get(i); instructionContext.accept(locationVisitor); } @@ -105,12 +123,18 @@ public XCFA visitMain(LitmusAArch64Parser.MainContext ctx) { for (Integer threadId : threadIds) { XcfaProcedureBuilder procBuilder = builders.get(threadId); procBuilder.createFinalLoc(); - procBuilder.addEdge(new XcfaEdge(lastLocation.get(threadId), procBuilder.getFinalLoc().get(), NopLabel.INSTANCE, EmptyMetaData.INSTANCE)); + procBuilder.addEdge( + new XcfaEdge( + lastLocation.get(threadId), + procBuilder.getFinalLoc().get(), + NopLabel.INSTANCE, + EmptyMetaData.INSTANCE)); } return builder.build(); } - private VarDecl getGlobalFromName(final String name, final LitExpr litExpr, final XcfaBuilder builder) { + private VarDecl getGlobalFromName( + final String name, final LitExpr litExpr, final XcfaBuilder builder) { if (!vars.containsKey(name)) { VarDecl var = Var(name, BvType(64)); checkNotNull(litExpr); @@ -121,7 +145,9 @@ private VarDecl getGlobalFromName(final String name, final LitExpr getOrCreateVar(final String name, final int size) { - checkState(!globalAddresses.get(currentProc).containsKey(name), "Register cannot be modified if it holds an address!"); + checkState( + !globalAddresses.get(currentProc).containsKey(name), + "Register cannot be modified if it holds an address!"); if (!regLookup.get(currentProc).containsKey(name)) { final VarDecl var = Var(name, BvType(size)); regLookup.get(currentProc).put(name, var); @@ -131,8 +157,12 @@ private VarDecl getOrCreateVar(final String name, final int size) { } private VarDecl getGlobalFromReg(final String name) { - checkState(!regLookup.get(currentProc).containsKey(name), "Register cannot be modified if it holds an address!"); - checkState(globalAddresses.get(currentProc).containsKey(name), "Register holds an unknown address!"); + checkState( + !regLookup.get(currentProc).containsKey(name), + "Register cannot be modified if it holds an address!"); + checkState( + globalAddresses.get(currentProc).containsKey(name), + "Register holds an unknown address!"); return globalAddresses.get(currentProc).get(name); } @@ -151,18 +181,23 @@ private XcfaLocation getOrCreateLoc(final String name) { private class ExpressionVisitor extends LitmusAArch64BaseVisitor> { @Override - public Expr visitExpressionConversion(LitmusAArch64Parser.ExpressionConversionContext ctx) { + public Expr visitExpressionConversion( + LitmusAArch64Parser.ExpressionConversionContext ctx) { return ctx.register32().accept(this); } @Override - public Expr visitExpressionImmediate64(LitmusAArch64Parser.ExpressionImmediate64Context ctx) { - return BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger(ctx.expressionImmediate().immediate().constant().getText()), 64); + public Expr visitExpressionImmediate64( + LitmusAArch64Parser.ExpressionImmediate64Context ctx) { + return BvUtils.bigIntegerToNeutralBvLitExpr( + new BigInteger(ctx.expressionImmediate().immediate().constant().getText()), 64); } @Override - public Expr visitExpressionImmediate32(LitmusAArch64Parser.ExpressionImmediate32Context ctx) { - return BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger(ctx.expressionImmediate().immediate().constant().getText()), 32); + public Expr visitExpressionImmediate32( + LitmusAArch64Parser.ExpressionImmediate32Context ctx) { + return BvUtils.bigIntegerToNeutralBvLitExpr( + new BigInteger(ctx.expressionImmediate().immediate().constant().getText()), 32); } @Override @@ -179,22 +214,38 @@ public Expr visitRegister32(LitmusAArch64Parser.Register32Context ctx) { private class LabelVisitor extends LitmusAArch64BaseVisitor { @Override public XcfaLabel visitMov32(LitmusAArch64Parser.Mov32Context ctx) { - return new StmtLabel(Assign(getOrCreateVar(ctx.r32.getText(), 32), ctx.expr32().accept(expressionVisitor))); + return new StmtLabel( + Assign( + getOrCreateVar(ctx.r32.getText(), 32), + ctx.expr32().accept(expressionVisitor))); } @Override public XcfaLabel visitMov64(LitmusAArch64Parser.Mov64Context ctx) { - return new StmtLabel(Assign(getOrCreateVar(ctx.r64.getText(), 64), ctx.expr64().accept(expressionVisitor))); + return new StmtLabel( + Assign( + getOrCreateVar(ctx.r64.getText(), 64), + ctx.expr64().accept(expressionVisitor))); } @Override public XcfaLabel visitCmp32(LitmusAArch64Parser.Cmp32Context ctx) { - return new StmtLabel(Assign(getOrCreateVar("Xcmp", 32), Sub(ctx.r32.accept(expressionVisitor), ctx.expr32().accept(expressionVisitor)))); + return new StmtLabel( + Assign( + getOrCreateVar("Xcmp", 32), + Sub( + ctx.r32.accept(expressionVisitor), + ctx.expr32().accept(expressionVisitor)))); } @Override public XcfaLabel visitCmp64(LitmusAArch64Parser.Cmp64Context ctx) { - return new StmtLabel(Assign(getOrCreateVar("Wcmp", 64), Sub(ctx.r64.accept(expressionVisitor), ctx.expr64().accept(expressionVisitor)))); + return new StmtLabel( + Assign( + getOrCreateVar("Wcmp", 64), + Sub( + ctx.r64.accept(expressionVisitor), + ctx.expr64().accept(expressionVisitor)))); } @Override @@ -208,7 +259,10 @@ public XcfaLabel visitArith32(LitmusAArch64Parser.Arith32Context ctx) { case "EOR" -> new StmtLabel(Assign(target, Xor(List.of(a, b)))); case "AND" -> new StmtLabel(Assign(target, And(List.of(a, b)))); default -> - throw new UnsupportedOperationException("Arithmetic instruction " + ctx.arithmeticInstruction().getText() + " not supported."); + throw new UnsupportedOperationException( + "Arithmetic instruction " + + ctx.arithmeticInstruction().getText() + + " not supported."); }; } @@ -223,41 +277,70 @@ public XcfaLabel visitArith64(LitmusAArch64Parser.Arith64Context ctx) { case "EOR" -> new StmtLabel(Assign(target, Xor(List.of(a, b)))); case "AND" -> new StmtLabel(Assign(target, And(List.of(a, b)))); default -> - throw new UnsupportedOperationException("Arithmetic instruction " + ctx.arithmeticInstruction().getText() + " not supported."); + throw new UnsupportedOperationException( + "Arithmetic instruction " + + ctx.arithmeticInstruction().getText() + + " not supported."); }; } @Override public XcfaLabel visitLoad32(LitmusAArch64Parser.Load32Context ctx) { final VarDecl var = getOrCreateVar(ctx.rD32.getText(), 32); - final VarDecl tmp = getOrCreateVar("tmp" + XcfaLocation.Companion.uniqueCounter(), 64); + final VarDecl tmp = + getOrCreateVar("tmp" + XcfaLocation.Companion.uniqueCounter(), 64); StmtLabel cast = new StmtLabel(Assign(var, Extract(tmp.getRef(), Int(0), Int(32)))); - ReadLabel load = new ReadLabel(getGlobalFromReg(ctx.address().r.getText()), tmp, Set.of(ctx.loadInstruction().mo), EmptyMetaData.INSTANCE); + ReadLabel load = + new ReadLabel( + getGlobalFromReg(ctx.address().r.getText()), + tmp, + Set.of(ctx.loadInstruction().mo), + EmptyMetaData.INSTANCE); return new SequenceLabel(List.of(load, cast)); } @Override public XcfaLabel visitLoad64(LitmusAArch64Parser.Load64Context ctx) { - return new ReadLabel(getGlobalFromReg(ctx.address().r.getText()), getOrCreateVar(ctx.rD64.getText(), 32), Set.of(ctx.loadInstruction().mo), EmptyMetaData.INSTANCE); + return new ReadLabel( + getGlobalFromReg(ctx.address().r.getText()), + getOrCreateVar(ctx.rD64.getText(), 32), + Set.of(ctx.loadInstruction().mo), + EmptyMetaData.INSTANCE); } @Override public XcfaLabel visitStore32(LitmusAArch64Parser.Store32Context ctx) { final VarDecl var = getOrCreateVar(ctx.rV32.getText(), 32); - final VarDecl tmp = getOrCreateVar("tmp" + XcfaLocation.Companion.uniqueCounter(), 64); + final VarDecl tmp = + getOrCreateVar("tmp" + XcfaLocation.Companion.uniqueCounter(), 64); StmtLabel cast = new StmtLabel(Assign(tmp, ZExt(var.getRef(), BvType(64)))); - WriteLabel store = new WriteLabel(getGlobalFromReg(ctx.address().r.getText()), tmp, Set.of(ctx.storeInstruction().mo), EmptyMetaData.INSTANCE); + WriteLabel store = + new WriteLabel( + getGlobalFromReg(ctx.address().r.getText()), + tmp, + Set.of(ctx.storeInstruction().mo), + EmptyMetaData.INSTANCE); return new SequenceLabel(List.of(cast, store)); } @Override public XcfaLabel visitStore64(LitmusAArch64Parser.Store64Context ctx) { - return new WriteLabel(getGlobalFromReg(ctx.address().r.getText()), getOrCreateVar(ctx.rV64.getText(), 64), Set.of(ctx.storeInstruction().mo), EmptyMetaData.INSTANCE); + return new WriteLabel( + getGlobalFromReg(ctx.address().r.getText()), + getOrCreateVar(ctx.rV64.getText(), 64), + Set.of(ctx.storeInstruction().mo), + EmptyMetaData.INSTANCE); } @Override public XcfaLabel visitFence(LitmusAArch64Parser.FenceContext ctx) { - return new FenceLabel(Set.of(ctx.Fence().getText() + (ctx.FenceOpt() == null ? "" : "." + ctx.FenceOpt().getText())), EmptyMetaData.INSTANCE); + return new FenceLabel( + Set.of( + ctx.Fence().getText() + + (ctx.FenceOpt() == null + ? "" + : "." + ctx.FenceOpt().getText())), + EmptyMetaData.INSTANCE); } } @@ -267,22 +350,52 @@ public XcfaLocation visitBranchRegister32(LitmusAArch64Parser.BranchRegister32Co VarDecl var = getOrCreateVar(ctx.rV32.getText(), 32); final StmtLabel stmt1, stmt2; if (ctx.branchRegInstruction().zerotest) { - stmt1 = new StmtLabel(Assume(Eq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 32)))); - stmt2 = new StmtLabel(Assume(Neq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 32)))); + stmt1 = + new StmtLabel( + Assume( + Eq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 32)))); + stmt2 = + new StmtLabel( + Assume( + Neq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 32)))); } else { - stmt1 = new StmtLabel(Assume(Neq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 32)))); - stmt2 = new StmtLabel(Assume(Eq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 32)))); + stmt1 = + new StmtLabel( + Assume( + Neq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 32)))); + stmt2 = + new StmtLabel( + Assume( + Eq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 32)))); } final XcfaLocation branchTo = getOrCreateLoc(ctx.label().getText()); final XcfaLocation newLoc = newAnonymousLoc(); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - branchTo, - stmt1, EmptyMetaData.INSTANCE)); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - newLoc, - stmt2, EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + branchTo, + stmt1, + EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + newLoc, + stmt2, + EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -292,22 +405,52 @@ public XcfaLocation visitBranchRegister64(LitmusAArch64Parser.BranchRegister64Co VarDecl var = getOrCreateVar(ctx.rV64.getText(), 64); final StmtLabel stmt1, stmt2; if (ctx.branchRegInstruction().zerotest) { - stmt1 = new StmtLabel(Assume(Eq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 64)))); - stmt2 = new StmtLabel(Assume(Neq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 64)))); + stmt1 = + new StmtLabel( + Assume( + Eq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 64)))); + stmt2 = + new StmtLabel( + Assume( + Neq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 64)))); } else { - stmt1 = new StmtLabel(Assume(Neq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 64)))); - stmt2 = new StmtLabel(Assume(Eq(var.getRef(), BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, 64)))); + stmt1 = + new StmtLabel( + Assume( + Neq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 64)))); + stmt2 = + new StmtLabel( + Assume( + Eq( + var.getRef(), + BvUtils.bigIntegerToNeutralBvLitExpr( + BigInteger.ZERO, 64)))); } final XcfaLocation branchTo = getOrCreateLoc(ctx.label().getText()); final XcfaLocation newLoc = newAnonymousLoc(); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - branchTo, - stmt1, EmptyMetaData.INSTANCE)); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - newLoc, - stmt2, EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + branchTo, + stmt1, + EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + newLoc, + stmt2, + EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -316,9 +459,13 @@ public XcfaLocation visitBranchRegister64(LitmusAArch64Parser.BranchRegister64Co public XcfaLocation visitBranch(LitmusAArch64Parser.BranchContext ctx) { final XcfaLocation branchTo = getOrCreateLoc(ctx.label().getText()); final XcfaLocation newLoc = newAnonymousLoc(); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - branchTo, NopLabel.INSTANCE, EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + branchTo, + NopLabel.INSTANCE, + EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -326,22 +473,30 @@ public XcfaLocation visitBranch(LitmusAArch64Parser.BranchContext ctx) { @Override public XcfaLocation visitBranchLabel(LitmusAArch64Parser.BranchLabelContext ctx) { final XcfaLocation newLoc = getOrCreateLoc(ctx.label().getText()); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - newLoc, NopLabel.INSTANCE, EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + newLoc, + NopLabel.INSTANCE, + EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @Override - public XcfaLocation visitSimpleInstruction(LitmusAArch64Parser.SimpleInstructionContext ctx) { + public XcfaLocation visitSimpleInstruction( + LitmusAArch64Parser.SimpleInstructionContext ctx) { final XcfaLabel label = ctx.accept(labelVisitor); if (label != null) { final XcfaLocation newLoc = newAnonymousLoc(); - builders.get(currentProc).addEdge(new XcfaEdge( - lastLocation.get(currentProc), - newLoc, - label, EmptyMetaData.INSTANCE)); + builders.get(currentProc) + .addEdge( + new XcfaEdge( + lastLocation.get(currentProc), + newLoc, + label, + EmptyMetaData.INSTANCE)); lastLocation.put(currentProc, newLoc); return newLoc; } @@ -349,7 +504,8 @@ public XcfaLocation visitSimpleInstruction(LitmusAArch64Parser.SimpleInstruction } @Override - public XcfaLocation visitExclusiveInstruction(LitmusAArch64Parser.ExclusiveInstructionContext ctx) { + public XcfaLocation visitExclusiveInstruction( + LitmusAArch64Parser.ExclusiveInstructionContext ctx) { throw new UnsupportedOperationException(); } } diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java index 422517ddfd..9d997a808d 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/LlvmMetadata.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.llvm2xcfa; import hu.bme.mit.theta.xcfa.model.MetaData; @@ -26,8 +25,7 @@ public LlvmMetadata(int lineNumber) { this.lineNumber = lineNumber; } - @NotNull - @Override + @NotNull @Override public MetaData combine(@NotNull MetaData other) { return this; } diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java index f07bf60d2a..13b3ab00f7 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/Utils.java @@ -13,9 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.llvm2xcfa; +import static hu.bme.mit.theta.core.decl.Decls.Var; +import static hu.bme.mit.theta.core.stmt.Stmts.Assign; +import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; +import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; + import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.stmt.Stmt; @@ -41,20 +48,11 @@ import hu.bme.mit.theta.xcfa.model.StmtLabel; import hu.bme.mit.theta.xcfa.model.XcfaEdge; import hu.bme.mit.theta.xcfa.model.XcfaLocation; - import java.math.BigInteger; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static hu.bme.mit.theta.core.decl.Decls.Var; -import static hu.bme.mit.theta.core.stmt.Stmts.Assign; -import static hu.bme.mit.theta.core.type.arraytype.ArrayExprs.Array; -import static hu.bme.mit.theta.core.type.booltype.BoolExprs.Bool; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.type.rattype.RatExprs.Rat; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; - public class Utils { private static final int doublePrecision = 1 << 8; public static ArithmeticType arithmeticType; @@ -86,7 +84,8 @@ public static Type createType(String type) { case "i1": return Bool(); default: -// new RuntimeException("Type " + type + " not known! (Using 32 bit int instead)").printStackTrace(); + // new RuntimeException("Type " + type + " not known! (Using 32 bit + // int instead)").printStackTrace(); if (arithmeticType == ArithmeticType.bitvector) return BvType.of(32); return Int(); } @@ -100,7 +99,9 @@ public static VarDecl createVariable(String name, String type) { public static LitExpr parseConstant(Type type, String value) { if (type instanceof RatType) - return RatLitExpr.of(BigInteger.valueOf((long) (Float.parseFloat(value) * doublePrecision)), BigInteger.valueOf(doublePrecision)); + return RatLitExpr.of( + BigInteger.valueOf((long) (Float.parseFloat(value) * doublePrecision)), + BigInteger.valueOf(doublePrecision)); return IntLitExpr.of(new BigInteger(value)); } @@ -111,15 +112,20 @@ public static LitExpr createConstant(String value) { public static LitExpr createConstant(Type type, String value) { String[] arguments = value.split(" "); if (arguments.length != 2) { - System.err.println("Constant should be of form \"(type=[a-zA-Z0-9]*) (value=[\\.0-9fe+-]*)\", got: " + value); + System.err.println( + "Constant should be of form \"(type=[a-zA-Z0-9]*) (value=[\\.0-9fe+-]*)\", got:" + + " " + + value); return getDefaultValue(type); - } switch (arguments[0]) { case "double": case "float": - return RatLitExpr.of(BigInteger.valueOf((long) (Float.parseFloat(arguments[1]) * doublePrecision)), BigInteger.valueOf(doublePrecision)); + return RatLitExpr.of( + BigInteger.valueOf( + (long) (Float.parseFloat(arguments[1]) * doublePrecision)), + BigInteger.valueOf(doublePrecision)); case "i64": if (arithmeticType == ArithmeticType.bitvector) return BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger(arguments[1]), 64); @@ -136,7 +142,9 @@ public static LitExpr createConstant(Type type, String value) { case "i1": return BoolLitExpr.of(arguments[1].equals("true")); default: - new RuntimeException("Type " + arguments[0] + " not known! (Using int32(0) instead)").printStackTrace(); + new RuntimeException( + "Type " + arguments[0] + " not known! (Using int32(0) instead)") + .printStackTrace(); if (arithmeticType == ArithmeticType.bitvector) return BvUtils.bigIntegerToNeutralBvLitExpr(new BigInteger("0"), 32); return IntLitExpr.of(BigInteger.ZERO); @@ -147,16 +155,25 @@ private static LitExpr getDefaultValue(Type type) { if (type instanceof RatType) return RatLitExpr.of(BigInteger.ZERO, BigInteger.ONE); else if (type instanceof BvType) return BvUtils.bigIntegerToNeutralBvLitExpr(BigInteger.ZERO, ((BvType) type).getSize()); - else if (type instanceof ArrayType) return ArrayLitExpr.of( - List.of(Tuple2.of(IntLitExpr.of(BigInteger.ZERO), cast(getDefaultValue(((ArrayType) type).getElemType()), ((ArrayType) type).getElemType()))), - cast(getDefaultValue(((ArrayType) type).getElemType()), ((ArrayType) type).getElemType()), - ArrayType.of(Int(), ((ArrayType) type).getElemType())); + else if (type instanceof ArrayType) + return ArrayLitExpr.of( + List.of( + Tuple2.of( + IntLitExpr.of(BigInteger.ZERO), + cast( + getDefaultValue(((ArrayType) type).getElemType()), + ((ArrayType) type).getElemType()))), + cast( + getDefaultValue(((ArrayType) type).getElemType()), + ((ArrayType) type).getElemType()), + ArrayType.of(Int(), ((ArrayType) type).getElemType())); return IntLitExpr.of(BigInteger.ZERO); } public static VarDecl getOrCreateVar(FunctionState functionState, Argument regArgument) { VarDecl var; - Tuple2, Integer> objects = functionState.getLocalVars().get(regArgument.getName()); + Tuple2, Integer> objects = + functionState.getLocalVars().get(regArgument.getName()); if (objects == null) { var = Var(regArgument.getName(), regArgument.getType()); functionState.getProcedureBuilder().getVars().add(var); @@ -178,28 +195,48 @@ public static VarDecl getOrCreateVar(FunctionState functionState, Argument re } } - public static void foldExpression(Instruction instruction, FunctionState functionState, BlockState blockState, String opName, Expr op, int ref) { + public static void foldExpression( + Instruction instruction, + FunctionState functionState, + BlockState blockState, + String opName, + Expr op, + int ref) { //noinspection OptionalGetWithoutIsPresent RegArgument ret = instruction.getRetVar().get(); if (ret instanceof LocalArgument) { - XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); + XcfaLocation loc = + new XcfaLocation( + blockState.getName() + "_" + blockState.getBlockCnt(), + EmptyMetaData.INSTANCE); VarDecl lhs = Utils.getOrCreateVar(functionState, ret); Stmt stmt = Assign(cast(lhs, lhs.getType()), cast(op, lhs.getType())); XcfaEdge edge; if (!lhs.getRef().equals(op)) - edge = new XcfaEdge(blockState.getLastLocation(), loc, new StmtLabel(stmt), new LlvmMetadata(instruction.getLineNumber())); + edge = + new XcfaEdge( + blockState.getLastLocation(), + loc, + new StmtLabel(stmt), + new LlvmMetadata(instruction.getLineNumber())); else - edge = new XcfaEdge(blockState.getLastLocation(), loc, NopLabel.INSTANCE, new LlvmMetadata(instruction.getLineNumber())); + edge = + new XcfaEdge( + blockState.getLastLocation(), + loc, + NopLabel.INSTANCE, + new LlvmMetadata(instruction.getLineNumber())); functionState.getProcedureBuilder().addLoc(loc); functionState.getProcedureBuilder().addEdge(edge); blockState.setLastLocation(loc); } else { if (functionState.getLocalVars().containsKey(opName)) { Tuple2, Integer> oldVar = functionState.getLocalVars().get(opName); - functionState.getLocalVars().put(ret.getName(), Tuple2.of(oldVar.get1(), oldVar.get2() + ref)); + functionState + .getLocalVars() + .put(ret.getName(), Tuple2.of(oldVar.get1(), oldVar.get2() + ref)); } functionState.getValues().put(ret.getName(), op); } } - } diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java index 45b7de6eae..0d6cc6e5a6 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/ArrayIntrinsicsHandler.java @@ -13,9 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.llvm2xcfa.handlers.concrete; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.stmt.Stmts.Assign; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; +import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; + import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.stmt.Stmt; import hu.bme.mit.theta.core.type.Expr; @@ -35,17 +40,16 @@ import hu.bme.mit.theta.xcfa.model.XcfaEdge; import hu.bme.mit.theta.xcfa.model.XcfaLocation; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.stmt.Stmts.Assign; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.Int; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; -import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; - public class ArrayIntrinsicsHandler extends BaseInstructionHandler { @Override - public void handleInstruction(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + public void handleInstruction( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { if (instruction.getOpName().equals("call")) { - String name = instruction.getArguments().get(instruction.getArguments().size() - 1).getName(); + String name = + instruction.getArguments().get(instruction.getArguments().size() - 1).getName(); if (name.startsWith("getArrayElement")) { getArrayElement(instruction, globalState, functionState, blockState); return; @@ -57,36 +61,69 @@ public void handleInstruction(Instruction instruction, GlobalState globalState, super.handleInstruction(instruction, globalState, functionState, blockState); } - private void getArrayElement(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void getArrayElement( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument arr = instruction.getArguments().get(0); Argument idx = instruction.getArguments().get(1); - checkState(arr.getType() instanceof ArrayType, "getArrayElement used on non-array type."); - checkState(idx.getType() == IntType.getInstance(), "getArrayElement used with non-int index."); - checkState(instruction.getRetVar().isPresent(), "getArrayElement used without return value."); + checkState( + arr.getType() instanceof ArrayType, + "getArrayElement used on non-array type."); + checkState( + idx.getType() == IntType.getInstance(), "getArrayElement used with non-int index."); + checkState( + instruction.getRetVar().isPresent(), "getArrayElement used without return value."); //noinspection unchecked - foldExpression(instruction, functionState, blockState, null, ArrayExprs.Read((Expr>) arr.getExpr(functionState.getValues()), cast(idx.getExpr(functionState.getValues()), Int())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + ArrayExprs.Read( + (Expr>) arr.getExpr(functionState.getValues()), + cast(idx.getExpr(functionState.getValues()), Int())), + 0); } - private void setArrayElement(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void setArrayElement( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument arr = instruction.getArguments().get(0); Argument idx = instruction.getArguments().get(1); Argument val = instruction.getArguments().get(2); - checkState(arr.getType() instanceof ArrayType, "getArrayElement used on non-array type."); - checkState(idx.getType() == IntType.getInstance(), "getArrayElement used with non-int index."); + checkState( + arr.getType() instanceof ArrayType, + "getArrayElement used on non-array type."); + checkState( + idx.getType() == IntType.getInstance(), "getArrayElement used with non-int index."); - XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); + XcfaLocation loc = + new XcfaLocation( + blockState.getName() + "_" + blockState.getBlockCnt(), + EmptyMetaData.INSTANCE); VarDecl var = functionState.getLocalVars().get(arr.getName()).get1(); - Expr expr = ArrayExprs.Write(cast(var.getRef(), ArrayType.of(Int(), val.getType())), cast(idx.getExpr(functionState.getValues()), Int()), cast(val.getExpr(functionState.getValues()), val.getType())); + Expr expr = + ArrayExprs.Write( + cast(var.getRef(), ArrayType.of(Int(), val.getType())), + cast(idx.getExpr(functionState.getValues()), Int()), + cast(val.getExpr(functionState.getValues()), val.getType())); Stmt stmt = Assign(cast(var, var.getType()), cast(expr, var.getType())); - XcfaEdge edge = new XcfaEdge(blockState.getLastLocation(), loc, new StmtLabel(stmt), new LlvmMetadata(instruction.getLineNumber())); + XcfaEdge edge = + new XcfaEdge( + blockState.getLastLocation(), + loc, + new StmtLabel(stmt), + new LlvmMetadata(instruction.getLineNumber())); functionState.getProcedureBuilder().addLoc(loc); functionState.getProcedureBuilder().addEdge(edge); blockState.setLastLocation(loc); } - - } diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java index 82c0a2414d..cf6132e31a 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/MemoryInstructionHandler.java @@ -13,9 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.llvm2xcfa.handlers.concrete; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.decl.Decls.Var; +import static hu.bme.mit.theta.core.stmt.Stmts.Assign; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; +import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; + import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.core.decl.VarDecl; import hu.bme.mit.theta.core.stmt.Stmt; @@ -32,18 +37,15 @@ import hu.bme.mit.theta.xcfa.model.StmtLabel; import hu.bme.mit.theta.xcfa.model.XcfaEdge; import hu.bme.mit.theta.xcfa.model.XcfaLocation; - import java.util.Optional; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.decl.Decls.Var; -import static hu.bme.mit.theta.core.stmt.Stmts.Assign; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; -import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; - public class MemoryInstructionHandler extends BaseInstructionHandler { @Override - public void handleInstruction(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + public void handleInstruction( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { switch (instruction.getOpName()) { case "alloca": alloca(instruction, globalState, functionState, blockState); @@ -65,24 +67,37 @@ public void handleInstruction(Instruction instruction, GlobalState globalState, super.handleInstruction(instruction, globalState, functionState, blockState); break; } - } - private void load(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void load( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument isatomic = instruction.getArguments().get(0); Argument op; checkState(instruction.getRetVar().isPresent(), "Load must load into a variable"); Argument ret = instruction.getRetVar().get(); - if (isatomic.getName().equals("atomic")) - op = instruction.getArguments().get(2); - else - op = instruction.getArguments().get(1); - checkState(functionState.getLocalVars().containsKey(op.getName()), "Load must load a variable!"); + if (isatomic.getName().equals("atomic")) op = instruction.getArguments().get(2); + else op = instruction.getArguments().get(1); + checkState( + functionState.getLocalVars().containsKey(op.getName()), + "Load must load a variable!"); - foldExpression(instruction, functionState, blockState, op.getName(), Utils.getOrCreateVar(functionState, op).getRef(), 1); + foldExpression( + instruction, + functionState, + blockState, + op.getName(), + Utils.getOrCreateVar(functionState, op).getRef(), + 1); } - private void store(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void store( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument isatomic = instruction.getArguments().get(0); Argument op1; Argument op2; @@ -95,13 +110,20 @@ private void store(Instruction instruction, GlobalState globalState, FunctionSta } Tuple2, Integer> oldVar = functionState.getLocalVars().get(op2.getName()); - Tuple2, Integer> potentialParam = functionState.getLocalVars().get(op1.getName()); - checkState(functionState.getLocalVars().containsKey(op2.getName()) || functionState.getParams().contains(oldVar.get1()), "Store must store into a variable!"); + Tuple2, Integer> potentialParam = + functionState.getLocalVars().get(op1.getName()); + checkState( + functionState.getLocalVars().containsKey(op2.getName()) + || functionState.getParams().contains(oldVar.get1()), + "Store must store into a variable!"); if (oldVar.get2() > 1) { - functionState.getLocalVars().put(op2.getName(), Tuple2.of(oldVar.get1(), oldVar.get2() - 1)); + functionState + .getLocalVars() + .put(op2.getName(), Tuple2.of(oldVar.get1(), oldVar.get2() - 1)); } else if (oldVar.get2() == 1) { - if (potentialParam != null && functionState.getParams().contains(potentialParam.get1())) { + if (potentialParam != null + && functionState.getParams().contains(potentialParam.get1())) { VarDecl var = functionState.getLocalVars().get(op2.getName()).get1(); functionState.getProcedureBuilder().getVars().remove(var); var = functionState.getLocalVars().get(op1.getName()).get1(); @@ -109,23 +131,41 @@ private void store(Instruction instruction, GlobalState globalState, FunctionSta functionState.getValues().put(op1.getName(), var.getRef()); functionState.getValues().put(op2.getName(), var.getRef()); } else { - XcfaLocation loc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); + XcfaLocation loc = + new XcfaLocation( + blockState.getName() + "_" + blockState.getBlockCnt(), + EmptyMetaData.INSTANCE); VarDecl var = functionState.getLocalVars().get(op2.getName()).get1(); - Stmt stmt = Assign(cast(var, var.getType()), cast(op1.getExpr(functionState.getValues()), var.getType())); - XcfaEdge edge = new XcfaEdge(blockState.getLastLocation(), loc, new StmtLabel(stmt), new LlvmMetadata(instruction.getLineNumber())); + Stmt stmt = + Assign( + cast(var, var.getType()), + cast(op1.getExpr(functionState.getValues()), var.getType())); + XcfaEdge edge = + new XcfaEdge( + blockState.getLastLocation(), + loc, + new StmtLabel(stmt), + new LlvmMetadata(instruction.getLineNumber())); functionState.getProcedureBuilder().addLoc(loc); functionState.getProcedureBuilder().addEdge(edge); blockState.setLastLocation(loc); } } - } - private void getelementptr(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void getelementptr( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { throw new RuntimeException("Not yet implemented!"); } - private void alloca(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void alloca( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Optional retVar = instruction.getRetVar(); checkState(retVar.isPresent(), "Alloca must have a variable tied to it"); VarDecl var = Var(retVar.get().getName(), retVar.get().getType()); diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java index 80690a6595..1109a27361 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/concrete/OtherInstructionHandler.java @@ -13,9 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.llvm2xcfa.handlers.concrete; +import static com.google.common.base.Preconditions.checkState; +import static hu.bme.mit.theta.core.stmt.Stmts.Assign; +import static hu.bme.mit.theta.core.stmt.Stmts.Havoc; +import static hu.bme.mit.theta.core.type.anytype.Exprs.Ite; +import static hu.bme.mit.theta.core.type.inttype.IntExprs.*; +import static hu.bme.mit.theta.core.utils.TypeUtils.cast; +import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; +import static hu.bme.mit.theta.llvm2xcfa.Utils.getOrCreateVar; + import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.Tuple4; import hu.bme.mit.theta.core.decl.VarDecl; @@ -37,23 +45,17 @@ import hu.bme.mit.theta.llvm2xcfa.handlers.states.GlobalState; import hu.bme.mit.theta.llvm2xcfa.handlers.utils.PlaceholderAssignmentStmt; import hu.bme.mit.theta.xcfa.model.*; - import java.util.ArrayList; import java.util.List; import java.util.Optional; -import static com.google.common.base.Preconditions.checkState; -import static hu.bme.mit.theta.core.stmt.Stmts.Assign; -import static hu.bme.mit.theta.core.stmt.Stmts.Havoc; -import static hu.bme.mit.theta.core.type.anytype.Exprs.Ite; -import static hu.bme.mit.theta.core.type.inttype.IntExprs.*; -import static hu.bme.mit.theta.core.utils.TypeUtils.cast; -import static hu.bme.mit.theta.llvm2xcfa.Utils.foldExpression; -import static hu.bme.mit.theta.llvm2xcfa.Utils.getOrCreateVar; - public class OtherInstructionHandler extends BaseInstructionHandler { @Override - public void handleInstruction(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + public void handleInstruction( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { switch (instruction.getOpName()) { case "icmp": icmp(instruction, globalState, functionState, blockState); @@ -80,13 +82,21 @@ public void handleInstruction(Instruction instruction, GlobalState globalState, super.handleInstruction(instruction, globalState, functionState, blockState); break; } - } - private void call(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { - Argument functionName = instruction.getArguments().get(instruction.getArguments().size() - 1); - XcfaLocation newLoc = new XcfaLocation(blockState.getName() + "_" + blockState.getBlockCnt(), EmptyMetaData.INSTANCE); - if (globalState.getProcedures().stream().anyMatch(objects -> objects.get1().equals(functionName.getName()))) { + private void call( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { + Argument functionName = + instruction.getArguments().get(instruction.getArguments().size() - 1); + XcfaLocation newLoc = + new XcfaLocation( + blockState.getName() + "_" + blockState.getBlockCnt(), + EmptyMetaData.INSTANCE); + if (globalState.getProcedures().stream() + .anyMatch(objects -> objects.get1().equals(functionName.getName()))) { System.err.println("More than one function."); System.exit(-80); } else { @@ -95,39 +105,64 @@ private void call(Instruction instruction, GlobalState globalState, FunctionStat stmts.add(havocVar(instruction.getRetVar().get(), functionState, blockState)); } for (Argument argument : instruction.getArguments()) { - Tuple2, Integer> objects = functionState.getLocalVars().get(argument.getName()); + Tuple2, Integer> objects = + functionState.getLocalVars().get(argument.getName()); if (objects != null && objects.get2() > 0) stmts.add(havocVar(argument, functionState, blockState)); } - XcfaEdge edge = new XcfaEdge(blockState.getLastLocation(), newLoc, new SequenceLabel(stmts.stream().map(stmt -> new StmtLabel(stmt)).toList()), new LlvmMetadata(instruction.getLineNumber())); + XcfaEdge edge = + new XcfaEdge( + blockState.getLastLocation(), + newLoc, + new SequenceLabel( + stmts.stream().map(stmt -> new StmtLabel(stmt)).toList()), + new LlvmMetadata(instruction.getLineNumber())); functionState.getProcedureBuilder().addLoc(newLoc); functionState.getProcedureBuilder().addEdge(edge); } blockState.setLastLocation(newLoc); } - private Stmt havocVar(Argument reg, FunctionState functionState, BlockState blockState) { VarDecl callVar = getOrCreateVar(functionState, reg); return Havoc(callVar); } - private void select(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void select( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument cond = instruction.getArguments().get(0); Argument op1 = instruction.getArguments().get(1); Argument op2 = instruction.getArguments().get(2); - checkState(cond.getType() == BoolType.getInstance(), "Select only supports boolean condition!"); + checkState( + cond.getType() == BoolType.getInstance(), + "Select only supports boolean condition!"); checkState(op1.getType().equals(op2.getType()), "Select only supports common types!"); checkState(instruction.getRetVar().isPresent(), "Instruction must have return variable"); Expr expr1 = op1.getExpr(functionState.getValues()); - //TODO: what to do, when null? + // TODO: what to do, when null? Expr expr2 = op2.getExpr(functionState.getValues()); - foldExpression(instruction, functionState, blockState, null, Ite(cast(cond.getExpr(functionState.getValues()), BoolType.getInstance()), cast(expr1, expr1.getType()), cast(expr2, expr1.getType())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Ite( + cast(cond.getExpr(functionState.getValues()), BoolType.getInstance()), + cast(expr1, expr1.getType()), + cast(expr2, expr1.getType())), + 0); } // Phi nodes are the only possible place where an argument might not be known yet. - private void phi(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void phi( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Optional retVar = instruction.getRetVar(); checkState(retVar.isPresent(), "Return var must be present!"); VarDecl phiVar = getOrCreateVar(functionState, retVar.get()); @@ -135,8 +170,19 @@ private void phi(Instruction instruction, GlobalState globalState, FunctionState Argument block = instruction.getArguments().get(2 * i + 1); Argument value = instruction.getArguments().get(2 * i); Tuple2 key = Tuple2.of(block.getName(), blockState.getName()); - Tuple4, Integer> val = functionState.getInterBlockEdges().getOrDefault(key, Tuple4.of(new XcfaLocation(key.get1(), EmptyMetaData.INSTANCE), new XcfaLocation(key.get2(), EmptyMetaData.INSTANCE), new ArrayList<>(), instruction.getLineNumber())); - checkState(phiVar.getType().equals(value.getType()), "phiVar and value has to be of the same type!"); + Tuple4, Integer> val = + functionState + .getInterBlockEdges() + .getOrDefault( + key, + Tuple4.of( + new XcfaLocation(key.get1(), EmptyMetaData.INSTANCE), + new XcfaLocation(key.get2(), EmptyMetaData.INSTANCE), + new ArrayList<>(), + instruction.getLineNumber())); + checkState( + phiVar.getType().equals(value.getType()), + "phiVar and value has to be of the same type!"); Stmt stmt; Expr expr; if ((expr = value.getExpr(functionState.getValues())) != null) { @@ -152,39 +198,105 @@ private void phi(Instruction instruction, GlobalState globalState, FunctionState } } - private void fcmp(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void fcmp( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument op1 = instruction.getArguments().get(0); Argument op2 = instruction.getArguments().get(1); Argument op3 = instruction.getArguments().get(2); - checkState(op1 instanceof StringArgument, "Icmp has to have string argument as first operand!"); + checkState( + op1 instanceof StringArgument, + "Icmp has to have string argument as first operand!"); checkState(op2.getType() == RatType.getInstance(), "Icmp only supports integer types!"); checkState(op3.getType() == RatType.getInstance(), "Icmp only supports integer types!"); checkState(instruction.getRetVar().isPresent(), "Instruction must have return variable"); switch (op1.getName()) { case "ueq": case "oeq": - foldExpression(instruction, functionState, blockState, null, RatExprs.Eq(cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), cast(op3.getExpr(functionState.getValues()), RatType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + RatExprs.Eq( + cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + RatType.getInstance())), + 0); break; case "one": case "une": - foldExpression(instruction, functionState, blockState, null, RatExprs.Neq(cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), cast(op3.getExpr(functionState.getValues()), RatType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + RatExprs.Neq( + cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + RatType.getInstance())), + 0); break; case "ugt": case "ogt": - foldExpression(instruction, functionState, blockState, null, RatExprs.Gt(cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), cast(op3.getExpr(functionState.getValues()), RatType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + RatExprs.Gt( + cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + RatType.getInstance())), + 0); break; case "uge": case "oge": - foldExpression(instruction, functionState, blockState, null, RatExprs.Geq(cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), cast(op3.getExpr(functionState.getValues()), RatType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + RatExprs.Geq( + cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + RatType.getInstance())), + 0); break; case "ult": case "olt": - foldExpression(instruction, functionState, blockState, null, RatExprs.Lt(cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), cast(op3.getExpr(functionState.getValues()), RatType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + RatExprs.Lt( + cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + RatType.getInstance())), + 0); break; case "ole": case "ule": - foldExpression(instruction, functionState, blockState, null, RatExprs.Leq(cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), cast(op3.getExpr(functionState.getValues()), RatType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + RatExprs.Leq( + cast(op2.getExpr(functionState.getValues()), RatType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + RatType.getInstance())), + 0); break; case "ord": case "true": @@ -198,37 +310,103 @@ private void fcmp(Instruction instruction, GlobalState globalState, FunctionStat } } - private void icmp(Instruction instruction, GlobalState globalState, FunctionState functionState, BlockState blockState) { + private void icmp( + Instruction instruction, + GlobalState globalState, + FunctionState functionState, + BlockState blockState) { Argument op1 = instruction.getArguments().get(0); Argument op2 = instruction.getArguments().get(1); Argument op3 = instruction.getArguments().get(2); - checkState(op1 instanceof StringArgument, "Icmp has to have string argument as first operand!"); + checkState( + op1 instanceof StringArgument, + "Icmp has to have string argument as first operand!"); checkState(op2.getType() == IntType.getInstance(), "Icmp only supports integer types!"); checkState(op3.getType() == IntType.getInstance(), "Icmp only supports integer types!"); checkState(instruction.getRetVar().isPresent(), "Instruction must have return variable"); switch (op1.getName()) { case "eq": - foldExpression(instruction, functionState, blockState, null, Eq(cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), cast(op3.getExpr(functionState.getValues()), IntType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Eq( + cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + IntType.getInstance())), + 0); break; case "ne": - foldExpression(instruction, functionState, blockState, null, Neq(cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), cast(op3.getExpr(functionState.getValues()), IntType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Neq( + cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + IntType.getInstance())), + 0); break; case "ugt": case "sgt": - foldExpression(instruction, functionState, blockState, null, Gt(cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), cast(op3.getExpr(functionState.getValues()), IntType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Gt( + cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + IntType.getInstance())), + 0); break; case "uge": case "sge": - foldExpression(instruction, functionState, blockState, null, Geq(cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), cast(op3.getExpr(functionState.getValues()), IntType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Geq( + cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + IntType.getInstance())), + 0); break; case "ult": case "slt": - foldExpression(instruction, functionState, blockState, null, Lt(cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), cast(op3.getExpr(functionState.getValues()), IntType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Lt( + cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + IntType.getInstance())), + 0); break; case "ule": case "sle": - foldExpression(instruction, functionState, blockState, null, Leq(cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), cast(op3.getExpr(functionState.getValues()), IntType.getInstance())), 0); + foldExpression( + instruction, + functionState, + blockState, + null, + Leq( + cast(op2.getExpr(functionState.getValues()), IntType.getInstance()), + cast( + op3.getExpr(functionState.getValues()), + IntType.getInstance())), + 0); break; default: throw new IllegalStateException("Unexpected value: " + op1.getName()); diff --git a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java index 7c4a26f388..691cee8555 100644 --- a/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java +++ b/subprojects/xcfa/llvm2xcfa/src/main/java/hu/bme/mit/theta/llvm2xcfa/handlers/states/FunctionState.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.llvm2xcfa.handlers.states; +import static hu.bme.mit.theta.llvm2xcfa.Utils.createVariable; + import hu.bme.mit.theta.common.Tuple2; import hu.bme.mit.theta.common.Tuple3; import hu.bme.mit.theta.common.Tuple4; @@ -32,7 +33,6 @@ import hu.bme.mit.theta.xcfa.model.XcfaLocation; import hu.bme.mit.theta.xcfa.model.XcfaProcedureBuilder; import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager; - import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -42,8 +42,6 @@ import java.util.Set; import java.util.stream.Collectors; -import static hu.bme.mit.theta.llvm2xcfa.Utils.createVariable; - public class FunctionState { private final GlobalState globalState; private final Tuple3, List>> function; @@ -52,20 +50,26 @@ public class FunctionState { private final Set> params; private final Map> values; private final Map locations; - private final Map, Tuple4, Integer>> interBlockEdges; + private final Map< + Tuple2, Tuple4, Integer>> + interBlockEdges; private VarDecl returnVar = null; - public FunctionState(GlobalState globalState, Tuple3, List>> function) { + public FunctionState( + GlobalState globalState, + Tuple3, List>> function) { this.globalState = globalState; this.function = function; procedureBuilder = new XcfaProcedureBuilder(function.get1(), new ProcedurePassManager()); -// procedureBuilder.setName(function.get1()); + // procedureBuilder.setName(function.get1()); localVars = new HashMap<>(); params = new HashSet<>(); values = new HashMap<>(); interBlockEdges = new HashMap<>(); - globalState.getGlobalVars().forEach((s, varDecl) -> localVars.put(s, Tuple2.of(varDecl, 1))); + globalState + .getGlobalVars() + .forEach((s, varDecl) -> localVars.put(s, Tuple2.of(varDecl, 1))); // Adding return variable if (function.get2().isPresent()) { @@ -74,7 +78,7 @@ public FunctionState(GlobalState globalState, Tuple3, L procedureBuilder.addParam(var, ParamDirection.OUT); localVars.put(function.get1() + "_ret", Tuple2.of(var, 1)); params.add(var); -// procedureBuilder.setRetType(var.getType()); + // procedureBuilder.setRetType(var.getType()); } // Adding params @@ -106,22 +110,39 @@ public FunctionState(GlobalState globalState, Tuple3, L } localVars.forEach((s, var) -> values.put(s, var.get1().getRef())); - } public void finalizeFunctionState(BuiltState builtState) { - interBlockEdges.forEach((_obj, edgeTup) -> { - List stmts = edgeTup.get3().stream().filter(stmt -> - !(stmt instanceof PlaceholderAssignmentStmt) || !((PlaceholderAssignmentStmt) stmt).isSelfAssignment(getValues()) - ).map(stmt -> { - if (stmt instanceof PlaceholderAssignmentStmt) { - return ((PlaceholderAssignmentStmt) stmt).toAssignStmt(getValues()); - } - return stmt; - }).collect(Collectors.toUnmodifiableList()); - XcfaEdge edge = new XcfaEdge(edgeTup.get1(), edgeTup.get2(), new SequenceLabel(stmts.stream().map(stmt -> new StmtLabel(stmt)).toList()), new LlvmMetadata(edgeTup.get4())); - procedureBuilder.addEdge(edge); - }); + interBlockEdges.forEach( + (_obj, edgeTup) -> { + List stmts = + edgeTup.get3().stream() + .filter( + stmt -> + !(stmt instanceof PlaceholderAssignmentStmt) + || !((PlaceholderAssignmentStmt) + stmt) + .isSelfAssignment(getValues())) + .map( + stmt -> { + if (stmt instanceof PlaceholderAssignmentStmt) { + return ((PlaceholderAssignmentStmt) stmt) + .toAssignStmt(getValues()); + } + return stmt; + }) + .collect(Collectors.toUnmodifiableList()); + XcfaEdge edge = + new XcfaEdge( + edgeTup.get1(), + edgeTup.get2(), + new SequenceLabel( + stmts.stream() + .map(stmt -> new StmtLabel(stmt)) + .toList()), + new LlvmMetadata(edgeTup.get4())); + procedureBuilder.addEdge(edge); + }); } public GlobalState getGlobalState() { @@ -148,7 +169,8 @@ public Map getLocations() { return locations; } - public Map, Tuple4, Integer>> getInterBlockEdges() { + public Map, Tuple4, Integer>> + getInterBlockEdges() { return interBlockEdges; } @@ -160,4 +182,3 @@ public VarDecl getReturnVar() { return returnVar; } } - diff --git a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt index b14d714142..e93dbb1ff1 100644 --- a/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt +++ b/subprojects/xcfa/xcfa-analysis/src/main/java/hu/bme/mit/theta/xcfa/analysis/XcfaAction.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.analysis import hu.bme.mit.theta.analysis.ptr.PtrAction @@ -24,37 +23,40 @@ import hu.bme.mit.theta.xcfa.passes.flatten data class XcfaAction @JvmOverloads -constructor(val pid: Int, val edge: XcfaEdge, private val lastWrites: WriteTriples = emptyMap(), - private val nextCnt: Int = 0) : - PtrAction(lastWrites, nextCnt) { - - val source: XcfaLocation = edge.source - val target: XcfaLocation = edge.target - val label: XcfaLabel = edge.label - private val stmts: List = label.toStmt().flatten() - - constructor(pid: Int, - source: XcfaLocation, - target: XcfaLocation, - label: XcfaLabel = NopLabel, - metaData: MetaData = EmptyMetaData, - lastWrites: WriteTriples = emptyMap(), - nextCnt: Int = 0) : - this(pid, XcfaEdge(source, target, label, metaData), lastWrites, nextCnt) - - override val stmtList: List - get() = stmts - - override fun toString(): String { - return "$pid: $source -> $target [${getStmts()}]" - } - - fun withLabel(sequenceLabel: SequenceLabel): XcfaAction { - return XcfaAction(pid, source, target, sequenceLabel, edge.metadata, nextCnt = nextCnt) - } - - fun withLastWrites(writeTriples: WriteTriples, nextCnt: Int): XcfaAction { - return XcfaAction(pid, source, target, label, edge.metadata, writeTriples, nextCnt) - } - +constructor( + val pid: Int, + val edge: XcfaEdge, + private val lastWrites: WriteTriples = emptyMap(), + private val nextCnt: Int = 0, +) : PtrAction(lastWrites, nextCnt) { + + val source: XcfaLocation = edge.source + val target: XcfaLocation = edge.target + val label: XcfaLabel = edge.label + private val stmts: List = label.toStmt().flatten() + + constructor( + pid: Int, + source: XcfaLocation, + target: XcfaLocation, + label: XcfaLabel = NopLabel, + metaData: MetaData = EmptyMetaData, + lastWrites: WriteTriples = emptyMap(), + nextCnt: Int = 0, + ) : this(pid, XcfaEdge(source, target, label, metaData), lastWrites, nextCnt) + + override val stmtList: List + get() = stmts + + override fun toString(): String { + return "$pid: $source -> $target [${getStmts()}]" + } + + fun withLabel(sequenceLabel: SequenceLabel): XcfaAction { + return XcfaAction(pid, source, target, sequenceLabel, edge.metadata, nextCnt = nextCnt) + } + + fun withLastWrites(writeTriples: WriteTriples, nextCnt: Int): XcfaAction { + return XcfaAction(pid, source, target, label, edge.metadata, writeTriples, nextCnt) + } } diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt index a35a2ed980..04a679d9e3 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaExplAnalysisTest.kt @@ -38,11 +38,11 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory import hu.bme.mit.theta.xcfa.analysis.coi.ConeOfInfluence import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread import hu.bme.mit.theta.xcfa.analysis.por.* +import java.util.* +import kotlin.random.Random import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource -import java.util.* -import kotlin.random.Random class XcfaExplAnalysisTest { diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt index c6932048db..cf094ab486 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaPredAnalysisTest.kt @@ -38,11 +38,11 @@ import hu.bme.mit.theta.solver.z3legacy.Z3LegacySolverFactory import hu.bme.mit.theta.xcfa.analysis.coi.ConeOfInfluence import hu.bme.mit.theta.xcfa.analysis.coi.XcfaCoiMultiThread import hu.bme.mit.theta.xcfa.analysis.por.* +import java.util.* +import kotlin.random.Random import org.junit.jupiter.api.Assertions import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.MethodSource -import java.util.* -import kotlin.random.Random class XcfaPredAnalysisTest { diff --git a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt index 67ffcf637f..3b144ffeb6 100644 --- a/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt +++ b/subprojects/xcfa/xcfa-analysis/src/test/java/hu/bme/mit/theta/xcfa/analysis/XcfaStateLtsTest.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.analysis import hu.bme.mit.theta.analysis.expl.ExplPrec @@ -24,139 +23,147 @@ import hu.bme.mit.theta.xcfa.analysis.XcfaProcessState.Companion.createLookup import hu.bme.mit.theta.xcfa.analysis.por.XcfaAasporLts import hu.bme.mit.theta.xcfa.analysis.por.XcfaSporLts import hu.bme.mit.theta.xcfa.model.* -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test import java.util.* import java.util.function.Predicate +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test class XcfaStateLtsTest { - @Test - fun testApply() { - val actionOrder: MutableList<(XcfaState>) -> XcfaAction> = ArrayList() - val expectations: MutableList>>> = ArrayList() - val lts = getXcfaLts() - lateinit var initState: XcfaState> - lateinit var xcfa: XCFA - - val edges: MutableList = ArrayList() - xcfa = xcfa("example") { - val proc1 = procedure("proc1") { - val a = "a" type IntExprs.Int() direction ParamDirection.IN - val b = "b" type IntExprs.Int() direction ParamDirection.OUT - - edges.add((init to final) { - b assign a.ref - }) - } - val main = procedure("main") { - val tmp = "tmp" type IntExprs.Int() - edges.add((init to "L1") { - proc1("1", tmp.ref) - }) - edges.add(("L1" to "L2") { - tmp.start(proc1, tmp.ref) - }) - edges.add(("L2" to final) { - tmp.join() - }) - } - - main.start() - } - initState = XcfaState( - xcfa, - mapOf( - Pair(0, - XcfaProcessState( - locs = LinkedList(listOf(edges[1].source)), - varLookup = LinkedList(listOf(createLookup(xcfa.initProcedures[0].first, "T0", "P0"))) - ) - ) + @Test + fun testApply() { + val actionOrder: MutableList<(XcfaState>) -> XcfaAction> = ArrayList() + val expectations: MutableList>>> = ArrayList() + val lts = getXcfaLts() + lateinit var initState: XcfaState> + lateinit var xcfa: XCFA + + val edges: MutableList = ArrayList() + xcfa = + xcfa("example") { + val proc1 = + procedure("proc1") { + val a = "a" type IntExprs.Int() direction ParamDirection.IN + val b = "b" type IntExprs.Int() direction ParamDirection.OUT + + edges.add((init to final) { b assign a.ref }) + } + val main = + procedure("main") { + val tmp = "tmp" type IntExprs.Int() + edges.add((init to "L1") { proc1("1", tmp.ref) }) + edges.add(("L1" to "L2") { tmp.start(proc1, tmp.ref) }) + edges.add(("L2" to final) { tmp.join() }) + } + + main.start() + } + initState = + XcfaState( + xcfa, + mapOf( + Pair( + 0, + XcfaProcessState( + locs = LinkedList(listOf(edges[1].source)), + varLookup = LinkedList(listOf(createLookup(xcfa.initProcedures[0].first, "T0", "P0"))), ), - PtrState(ExplState.bottom()) - ) - val sporLts = XcfaSporLts(xcfa) - val aasporLts = XcfaAasporLts(xcfa, LinkedHashMap()) - - actionOrder.add { XcfaAction(0, edges[1]) } - expectations.add { - it.processes[0]!!.locs.size == 2 && it.processes[0]!!.locs.peek() == edges[0].source && - lts.getEnabledActionsFor(it).size == 1 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + ) + ), + PtrState(ExplState.bottom()), + ) + val sporLts = XcfaSporLts(xcfa) + val aasporLts = XcfaAasporLts(xcfa, LinkedHashMap()) + + actionOrder.add { XcfaAction(0, edges[1]) } + expectations.add { + it.processes[0]!!.locs.size == 2 && + it.processes[0]!!.locs.peek() == edges[0].source && + lts.getEnabledActionsFor(it).size == 1 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - actionOrder.add { XcfaAction(0, edges[0]) } - expectations.add { - it.processes[0]!!.locs.size == 2 && it.processes[0]!!.locs.peek() == edges[0].target && - lts.getEnabledActionsFor(it).size == 1 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + actionOrder.add { XcfaAction(0, edges[0]) } + expectations.add { + it.processes[0]!!.locs.size == 2 && + it.processes[0]!!.locs.peek() == edges[0].target && + lts.getEnabledActionsFor(it).size == 1 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - actionOrder.add { - XcfaAction( - 0, XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel), EmptyMetaData) - ) - } - expectations.add { - it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[1].target && - lts.getEnabledActionsFor(it).size == 1 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + actionOrder.add { + XcfaAction( + 0, + XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel), EmptyMetaData), + ) + } + expectations.add { + it.processes[0]!!.locs.size == 1 && + it.processes[0]!!.locs.peek() == edges[1].target && + lts.getEnabledActionsFor(it).size == 1 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - actionOrder.add { XcfaAction(0, edges[2]) } - expectations.add { - it.processes.size == 2 && - it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[2].target && - it.processes[it.foreignKey()!!]!!.locs.size == 1 && it.processes[it.foreignKey()!!]!!.locs.peek() == edges[0].source && - lts.getEnabledActionsFor(it).size == 2 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + actionOrder.add { XcfaAction(0, edges[2]) } + expectations.add { + it.processes.size == 2 && + it.processes[0]!!.locs.size == 1 && + it.processes[0]!!.locs.peek() == edges[2].target && + it.processes[it.foreignKey()!!]!!.locs.size == 1 && + it.processes[it.foreignKey()!!]!!.locs.peek() == edges[0].source && + lts.getEnabledActionsFor(it).size == 2 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - actionOrder.add { s -> XcfaAction(s.foreignKey()!!, edges[0]) } - expectations.add { - it.processes.size == 2 && - it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[2].target && - it.processes[it.foreignKey()!!]!!.locs.size == 1 && it.processes[it.foreignKey()!!]!!.locs.peek() == edges[0].target && - lts.getEnabledActionsFor(it).size == 2 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + actionOrder.add { s -> XcfaAction(s.foreignKey()!!, edges[0]) } + expectations.add { + it.processes.size == 2 && + it.processes[0]!!.locs.size == 1 && + it.processes[0]!!.locs.peek() == edges[2].target && + it.processes[it.foreignKey()!!]!!.locs.size == 1 && + it.processes[it.foreignKey()!!]!!.locs.peek() == edges[0].target && + lts.getEnabledActionsFor(it).size == 2 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - actionOrder.add { s -> - XcfaAction( - s.foreignKey()!!, XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel), EmptyMetaData) - ) - } - expectations.add { - it.processes.size == 1 && it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[2].target && - lts.getEnabledActionsFor(it).size == 1 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + actionOrder.add { s -> + XcfaAction( + s.foreignKey()!!, + XcfaEdge(edges[0].target, edges[0].target, ReturnLabel(NopLabel), EmptyMetaData), + ) + } + expectations.add { + it.processes.size == 1 && + it.processes[0]!!.locs.size == 1 && + it.processes[0]!!.locs.peek() == edges[2].target && + lts.getEnabledActionsFor(it).size == 1 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - actionOrder.add { XcfaAction(0, edges[3]) } - expectations.add { - it.processes[0]!!.locs.size == 1 && it.processes[0]!!.locs.peek() == edges[3].target && - lts.getEnabledActionsFor(it).size == 1 && - sporLts.getEnabledActionsFor(it).size == 1 && - aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 - } + actionOrder.add { XcfaAction(0, edges[3]) } + expectations.add { + it.processes[0]!!.locs.size == 1 && + it.processes[0]!!.locs.peek() == edges[3].target && + lts.getEnabledActionsFor(it).size == 1 && + sporLts.getEnabledActionsFor(it).size == 1 && + aasporLts.getEnabledActionsFor(it, emptyList(), ExplPrec.empty()).size == 1 + } - var state = initState - for ((index, xcfaAction) in actionOrder.withIndex()) { - println("Test $index: $xcfaAction") - val newState = state.apply(xcfaAction(state)) - assertTrue(expectations[index].test(newState.first)) - state = newState.first - println("Test $index OK") - } + var state = initState + for ((index, xcfaAction) in actionOrder.withIndex()) { + println("Test $index: $xcfaAction") + val newState = state.apply(xcfaAction(state)) + assertTrue(expectations[index].test(newState.first)) + state = newState.first + println("Test $index OK") } + } } -private fun XcfaState<*>.foreignKey(): Int? = - processes.keys.firstOrNull { key -> key != 0 } +private fun XcfaState<*>.foreignKey(): Int? = processes.keys.firstOrNull { key -> key != 0 } diff --git a/subprojects/xcfa/xcfa-cli/build.gradle.kts b/subprojects/xcfa/xcfa-cli/build.gradle.kts index 83c5989fe7..63d27c1109 100644 --- a/subprojects/xcfa/xcfa-cli/build.gradle.kts +++ b/subprojects/xcfa/xcfa-cli/build.gradle.kts @@ -51,4 +51,3 @@ dependencies { application { mainClass.set("hu.bme.mit.theta.xcfa.cli.XcfaCli") } - 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 e5370bdf2e..29d44360d2 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 @@ -32,105 +32,102 @@ import java.io.File import java.io.FileReader import kotlin.system.exitProcess - class XcfaCli(private val args: Array) { - @Parameter(names = ["--config", "-c"], description = "Configuration file (CLI options will overwrite these!)") - var configFile: File? = null - - @Parameter(names = ["--help", "-h"], help = true) - private var help = false - - @Parameter(names = ["--svcomp"]) - private var svcomp = false - - @Parameter - var remainingFlags: MutableList = ArrayList() - - private fun run() { - lateinit var config: XcfaConfig<*, *> - /// Checking flags - try { - JCommander.newBuilder().addObject(this).programName(JAR_NAME).build().parse(*args) - val configFile = this.configFile - if (configFile != null) { - config = getGson().fromJson(FileReader(configFile), XcfaConfig::class.java) - } else { - config = XcfaConfig() - } - if (svcomp) { - remainingFlags.addAll( - listOf( - "--enable-output", - "--disable-xcfa-serialization", - "--disable-arg-generation", - "--disable-chc-serialization", - "--disable-c-serialization", - "--only-svcomp-witness", - ) - ) - if (!remainingFlags.contains("--backend")) { - remainingFlags.addAll(listOf("--backend", "PORTFOLIO")) - } - } - while (remainingFlags.isNotEmpty()) { - val nextArgs = remainingFlags.toTypedArray() - remainingFlags.clear() - val builder = JCommander.newBuilder().addObject(this) - for (obj in config.getObjects()) { - builder.addObject(obj) - } - builder.programName(JAR_NAME).build().parse(*nextArgs) - if (!config.update() && remainingFlags.isNotEmpty()) { - throw ParameterException("Extraneous parameters: $remainingFlags") - } - } - } catch (ex: ParameterException) { - println("Invalid parameters, details:") - ex.printStackTrace() - ex.usage() - exitProcess(ExitCodes.INVALID_PARAM.code) - } catch (ex: JsonIOException) { - println("There was a problem reading from ${configFile}:") - ex.printStackTrace() - exitProcess(ExitCodes.INVALID_PARAM.code) - } catch (ex: JsonSyntaxException) { - println("There was a problem parsing ${configFile}:") - ex.printStackTrace() - exitProcess(ExitCodes.INVALID_PARAM.code) + @Parameter( + names = ["--config", "-c"], + description = "Configuration file (CLI options will overwrite these!)", + ) + var configFile: File? = null + + @Parameter(names = ["--help", "-h"], help = true) private var help = false + + @Parameter(names = ["--svcomp"]) private var svcomp = false + + @Parameter var remainingFlags: MutableList = ArrayList() + + private fun run() { + lateinit var config: XcfaConfig<*, *> + /// Checking flags + try { + JCommander.newBuilder().addObject(this).programName(JAR_NAME).build().parse(*args) + val configFile = this.configFile + if (configFile != null) { + config = getGson().fromJson(FileReader(configFile), XcfaConfig::class.java) + } else { + config = XcfaConfig() + } + if (svcomp) { + remainingFlags.addAll( + listOf( + "--enable-output", + "--disable-xcfa-serialization", + "--disable-arg-generation", + "--disable-chc-serialization", + "--disable-c-serialization", + "--only-svcomp-witness", + ) + ) + if (!remainingFlags.contains("--backend")) { + remainingFlags.addAll(listOf("--backend", "PORTFOLIO")) } - - - if (help) { - val builder = JCommander.newBuilder().addObject(this) - for (obj in config.getObjects()) { - builder.addObject(obj) - } - builder.build().usage() - return + } + while (remainingFlags.isNotEmpty()) { + val nextArgs = remainingFlags.toTypedArray() + remainingFlags.clear() + val builder = JCommander.newBuilder().addObject(this) + for (obj in config.getObjects()) { + builder.addObject(obj) } - - /// version - if (config.outputConfig.versionInfo) { - CliUtils.printVersion(System.out) - return + builder.programName(JAR_NAME).build().parse(*nextArgs) + if (!config.update() && remainingFlags.isNotEmpty()) { + throw ParameterException("Extraneous parameters: $remainingFlags") } + } + } catch (ex: ParameterException) { + println("Invalid parameters, details:") + ex.printStackTrace() + ex.usage() + exitProcess(ExitCodes.INVALID_PARAM.code) + } catch (ex: JsonIOException) { + println("There was a problem reading from ${configFile}:") + ex.printStackTrace() + exitProcess(ExitCodes.INVALID_PARAM.code) + } catch (ex: JsonSyntaxException) { + println("There was a problem parsing ${configFile}:") + ex.printStackTrace() + exitProcess(ExitCodes.INVALID_PARAM.code) + } - val logger = ConsoleLogger(config.debugConfig.logLevel) - val uniqueLogger = UniqueWarningLogger(logger) + if (help) { + val builder = JCommander.newBuilder().addObject(this) + for (obj in config.getObjects()) { + builder.addObject(obj) + } + builder.build().usage() + return + } - runConfig(config, logger, uniqueLogger, false) + /// version + if (config.outputConfig.versionInfo) { + CliUtils.printVersion(System.out) + return } + val logger = ConsoleLogger(config.debugConfig.logLevel) + val uniqueLogger = UniqueWarningLogger(logger) - companion object { + runConfig(config, logger, uniqueLogger, false) + } - private const val JAR_NAME = "theta-xcfa-cli.jar" + companion object { - @JvmStatic - fun main(args: Array) { - val mainApp = XcfaCli(args) - mainApp.run() - } + private const val JAR_NAME = "theta-xcfa-cli.jar" + + @JvmStatic + fun main(args: Array) { + val mainApp = XcfaCli(args) + mainApp.run() } + } } diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt index 881a3202cf..264f014285 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GraphmlWitnessWriter.kt @@ -36,92 +36,126 @@ import java.util.* class GraphmlWitnessWriter { - fun writeWitness( - safetyResult: SafetyResult<*, *>, - inputFile: File, - cexSolverFactory: SolverFactory, - parseContext: ParseContext, - witnessfile: File, - ) { - // TODO eliminate the need for the instanceof check - if (safetyResult.isUnsafe && safetyResult.asUnsafe().cex is Trace<*, *>) { - val concrTrace: Trace, XcfaAction> = XcfaTraceConcretizer.concretize( - safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, cexSolverFactory, - parseContext) + fun writeWitness( + safetyResult: SafetyResult<*, *>, + inputFile: File, + cexSolverFactory: SolverFactory, + parseContext: ParseContext, + witnessfile: File, + ) { + // TODO eliminate the need for the instanceof check + if (safetyResult.isUnsafe && safetyResult.asUnsafe().cex is Trace<*, *>) { + val concrTrace: Trace, XcfaAction> = + XcfaTraceConcretizer.concretize( + safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, + cexSolverFactory, + parseContext, + ) - val witnessTrace = traceToWitness(trace = concrTrace, parseContext = parseContext) - val graphmlWitness = GraphmlWitness(witnessTrace, inputFile) - val xml = graphmlWitness.toPrettyXml() - witnessfile.writeText(xml) - } else if (safetyResult.isSafe) { - val taskHash = WitnessWriter.createTaskHash(inputFile.absolutePath) - val dummyWitness = StringBuilder() - dummyWitness.append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "false").append(System.lineSeparator()).append( - "").append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "false").append(System.lineSeparator()).append( - "").append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "") - .append(System.lineSeparator()).append( - "").append(System.lineSeparator()).append( - "correctness_witness") - .append(System.lineSeparator()).append( - "theta").append(System.lineSeparator()).append( - "CHECK( init(main()), LTL(G ! call(reach_error())) )") - .append(System.lineSeparator()).append( - "C").append(System.lineSeparator()).append( - "32bit").append(System.lineSeparator()) - .append( - "") - dummyWitness.append(taskHash) - dummyWitness.append("").append(System.lineSeparator()).append( - "") + val witnessTrace = traceToWitness(trace = concrTrace, parseContext = parseContext) + val graphmlWitness = GraphmlWitness(witnessTrace, inputFile) + val xml = graphmlWitness.toPrettyXml() + witnessfile.writeText(xml) + } else if (safetyResult.isSafe) { + val taskHash = WitnessWriter.createTaskHash(inputFile.absolutePath) + val dummyWitness = StringBuilder() + dummyWitness + .append( + "" + ) + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("false") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("false") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append( + "" + ) + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append( + "" + ) + .append(System.lineSeparator()) + .append( + "" + ) + .append(System.lineSeparator()) + .append( + "" + ) + .append(System.lineSeparator()) + .append( + "" + ) + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("correctness_witness") + .append(System.lineSeparator()) + .append("theta") + .append(System.lineSeparator()) + .append( + "CHECK( init(main()), LTL(G ! call(reach_error())) )" + ) + .append(System.lineSeparator()) + .append("C") + .append(System.lineSeparator()) + .append("32bit") + .append(System.lineSeparator()) + .append("") + dummyWitness.append(taskHash) + dummyWitness + .append("") + .append(System.lineSeparator()) + .append("") - val tz: TimeZone = TimeZone.getTimeZone("UTC") - val df: DateFormat = SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss'Z'") // Quoted "Z" to indicate UTC, no timezone offset + val tz: TimeZone = TimeZone.getTimeZone("UTC") + val df: DateFormat = + SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'" + ) // Quoted "Z" to indicate UTC, no timezone offset - df.timeZone = tz - val isoDate: String = df.format(Date()) + df.timeZone = tz + val isoDate: String = df.format(Date()) - dummyWitness.append(isoDate) - dummyWitness.append("").append(System.lineSeparator()).append( - "") - dummyWitness.append(inputFile.name) - dummyWitness.append("").append(System.lineSeparator()).append( - "").append(System.lineSeparator()).append( - "true").append(System.lineSeparator()).append( - "").append(System.lineSeparator()).append( - "").append(System.lineSeparator()).append( - "") + dummyWitness.append(isoDate) + dummyWitness + .append("") + .append(System.lineSeparator()) + .append("") + dummyWitness.append(inputFile.name) + dummyWitness + .append("") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("true") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("") + .append(System.lineSeparator()) + .append("") - try { - BufferedWriter(FileWriter(witnessfile)).use { bw -> - bw.write(dummyWitness.toString()) - } - } catch (ioe: IOException) { - ioe.printStackTrace() - } - } + try { + BufferedWriter(FileWriter(witnessfile)).use { bw -> bw.write(dummyWitness.toString()) } + } catch (ioe: IOException) { + ioe.printStackTrace() + } } -} \ No newline at end of file + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt index a7e0b45aa3..d38d2c3b64 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/GsonUtils.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.utils import com.google.gson.Gson @@ -55,83 +54,136 @@ import java.io.File import java.util.* private fun argAdapterHelper(stateType: java.lang.reflect.Type): java.lang.reflect.Type = - TypeToken.getParameterized( - TypeToken.get(ArgAdapterHelper::class.java).type, - TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, stateType).type, - TypeToken.get(XcfaAction::class.java).type, - ).type + TypeToken.getParameterized( + TypeToken.get(ArgAdapterHelper::class.java).type, + TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, stateType).type, + TypeToken.get(XcfaAction::class.java).type, + ) + .type private fun argHelper(stateType: java.lang.reflect.Type): java.lang.reflect.Type = - TypeToken.getParameterized( - TypeToken.get(ARG::class.java).type, - TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, stateType).type, - TypeToken.get(XcfaAction::class.java).type, - ).type + TypeToken.getParameterized( + TypeToken.get(ARG::class.java).type, + TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, stateType).type, + TypeToken.get(XcfaAction::class.java).type, + ) + .type private fun traceHelper(stateType: java.lang.reflect.Type): java.lang.reflect.Type = - TypeToken.getParameterized( - TypeToken.get(Trace::class.java).type, - TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, stateType).type, - TypeToken.get(XcfaAction::class.java).type, - ).type + TypeToken.getParameterized( + TypeToken.get(Trace::class.java).type, + TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, stateType).type, + TypeToken.get(XcfaAction::class.java).type, + ) + .type @JvmOverloads -internal fun getGson(xcfa: XCFA, domain: () -> Domain = { error("Domain needs to be specified.") }, - solver: () -> Solver = { error("Solver is necessary.") }): Gson { - val (scope, env) = xcfa.getSymbols() - return getGson(scope, env, false, domain, solver) +internal fun getGson( + xcfa: XCFA, + domain: () -> Domain = { error("Domain needs to be specified.") }, + solver: () -> Solver = { error("Solver is necessary.") }, +): Gson { + val (scope, env) = xcfa.getSymbols() + return getGson(scope, env, false, domain, solver) } @JvmOverloads -internal fun getGson(domain: () -> Domain = { error("Domain needs to be specified.") }, - solver: () -> Solver = { error("Solver is necessary.") }): Gson { - return getGson(XcfaScope(SymbolTable()), Env(), true, domain, solver) +internal fun getGson( + domain: () -> Domain = { error("Domain needs to be specified.") }, + solver: () -> Solver = { error("Solver is necessary.") }, +): Gson { + return getGson(XcfaScope(SymbolTable()), Env(), true, domain, solver) } -private fun getGson(scope: XcfaScope, env: Env, newScope: Boolean, domain: () -> Domain, - solver: () -> Solver): Gson { - val gsonBuilder = GsonBuilder() - lateinit var gson: Gson - gsonBuilder.registerTypeHierarchyAdapter(FrontendConfig::class.java, SpecFrontendConfigTypeAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(BackendConfig::class.java, SpecBackendConfigTypeAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(File::class.java, StringTypeAdapter { File(it) }) - gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, XcfaLocationAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(XCFA::class.java, XcfaAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(VarDecl::class.java, - VarDeclAdapter({ gson }, scope, env, !newScope)) - gsonBuilder.registerTypeHierarchyAdapter(Stmt::class.java, - StringTypeAdapter { StatementWrapper(it, scope).instantiate(env) }) - gsonBuilder.registerTypeHierarchyAdapter(Expr::class.java, - StringTypeAdapter { ExpressionWrapper(scope, it).instantiate(env) }) - gsonBuilder.registerTypeHierarchyAdapter(Type::class.java, - StringTypeAdapter { TypeWrapper(it).instantiate() }) - gsonBuilder.registerTypeHierarchyAdapter(VarIndexing::class.java, - StringTypeAdapter { BasicVarIndexing.fromString(it, scope, env) }) - gsonBuilder.registerTypeHierarchyAdapter(ExplState::class.java, ExplStateAdapter(scope, env)) - gsonBuilder.registerTypeHierarchyAdapter(PredState::class.java, - PredStateAdapter({ gson }, scope, env)) - gsonBuilder.registerTypeHierarchyAdapter(XcfaLabel::class.java, - XcfaLabelAdapter(scope, env, { gson })) - gsonBuilder.registerTypeHierarchyAdapter(MetaData::class.java, MetaDataAdapter()) - gsonBuilder.registerTypeHierarchyAdapter(Pair::class.java, PairAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(Optional::class.java, OptionalAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(XcfaState::class.java, - XcfaStateAdapter({ gson }) { domain().stateType }) - gsonBuilder.registerTypeHierarchyAdapter(XcfaAction::class.java, XcfaActionAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(Trace::class.java, TraceAdapter({ gson }, { - TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, - domain().stateType).type - }, TypeToken.get(XcfaAction::class.java).type)) - gsonBuilder.registerTypeHierarchyAdapter(ARG::class.java, - ArgAdapter({ gson }, { domain().partialOrd(solver()) }, - { argAdapterHelper(domain().stateType) })) - gsonBuilder.registerTypeHierarchyAdapter(SafetyResult::class.java, - SafetyResultAdapter({ gson }, { argHelper(domain().stateType) }, - { traceHelper(domain().stateType) })) - gsonBuilder.registerTypeHierarchyAdapter(ParseContext::class.java, - ParseContextAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(FrontendMetadata::class.java, - FrontendMetadataAdapter { gson }) - gson = gsonBuilder.create() - return gson -} \ No newline at end of file +private fun getGson( + scope: XcfaScope, + env: Env, + newScope: Boolean, + domain: () -> Domain, + solver: () -> Solver, +): Gson { + val gsonBuilder = GsonBuilder() + lateinit var gson: Gson + gsonBuilder.registerTypeHierarchyAdapter( + FrontendConfig::class.java, + SpecFrontendConfigTypeAdapter { gson }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + BackendConfig::class.java, + SpecBackendConfigTypeAdapter { gson }, + ) + gsonBuilder.registerTypeHierarchyAdapter(File::class.java, StringTypeAdapter { File(it) }) + gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, XcfaLocationAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter(XCFA::class.java, XcfaAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter( + VarDecl::class.java, + VarDeclAdapter({ gson }, scope, env, !newScope), + ) + gsonBuilder.registerTypeHierarchyAdapter( + Stmt::class.java, + StringTypeAdapter { StatementWrapper(it, scope).instantiate(env) }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + Expr::class.java, + StringTypeAdapter { ExpressionWrapper(scope, it).instantiate(env) }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + Type::class.java, + StringTypeAdapter { TypeWrapper(it).instantiate() }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + VarIndexing::class.java, + StringTypeAdapter { BasicVarIndexing.fromString(it, scope, env) }, + ) + gsonBuilder.registerTypeHierarchyAdapter(ExplState::class.java, ExplStateAdapter(scope, env)) + gsonBuilder.registerTypeHierarchyAdapter( + PredState::class.java, + PredStateAdapter({ gson }, scope, env), + ) + gsonBuilder.registerTypeHierarchyAdapter( + XcfaLabel::class.java, + XcfaLabelAdapter(scope, env, { gson }), + ) + gsonBuilder.registerTypeHierarchyAdapter(MetaData::class.java, MetaDataAdapter()) + gsonBuilder.registerTypeHierarchyAdapter(Pair::class.java, PairAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter(Optional::class.java, OptionalAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter( + XcfaState::class.java, + XcfaStateAdapter({ gson }) { domain().stateType }, + ) + gsonBuilder.registerTypeHierarchyAdapter(XcfaAction::class.java, XcfaActionAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter( + Trace::class.java, + TraceAdapter( + { gson }, + { + TypeToken.getParameterized(TypeToken.get(XcfaState::class.java).type, domain().stateType) + .type + }, + TypeToken.get(XcfaAction::class.java).type, + ), + ) + gsonBuilder.registerTypeHierarchyAdapter( + ARG::class.java, + ArgAdapter( + { gson }, + { domain().partialOrd(solver()) }, + { argAdapterHelper(domain().stateType) }, + ), + ) + gsonBuilder.registerTypeHierarchyAdapter( + SafetyResult::class.java, + SafetyResultAdapter( + { gson }, + { argHelper(domain().stateType) }, + { traceHelper(domain().stateType) }, + ), + ) + gsonBuilder.registerTypeHierarchyAdapter(ParseContext::class.java, ParseContextAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter( + FrontendMetadata::class.java, + FrontendMetadataAdapter { gson }, + ) + gson = gsonBuilder.create() + return gson +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt index ae39115e9f..f1d2efd0fb 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/utils/YmlWitnessWriter.kt @@ -37,159 +37,189 @@ import hu.bme.mit.theta.xcfa.toC import java.io.File import java.util.* - class YmlWitnessWriter { - fun writeWitness( - safetyResult: SafetyResult<*, *>, - inputFile: File, - property: ErrorDetection, - architecture: ArchitectureConfig.ArchitectureType?, - cexSolverFactory: SolverFactory, - parseContext: ParseContext, - witnessfile: File, - ) { - val metadata = Metadata( - formatVersion = "2.0", - uuid = UUID.randomUUID().toString(), - creationTime = getIsoDate(), - producer = Producer( - name = (System.getenv("VERIFIER_NAME")?:"").ifEmpty { "Theta" }, - version = (System.getenv("VERIFIER_VERSION")?:"").ifEmpty { "no version found" }, - ), - task = Task( - inputFiles = listOf(inputFile.name), - inputFileHashes = listOf(createTaskHash(inputFile.path)), - specification = property.name, - dataModel = architecture?.let { if(it == ArchitectureConfig.ArchitectureType.ILP32) DataModel.ILP32 else DataModel.LP64 } ?: DataModel.ILP32, - language = Language.C, - ) + fun writeWitness( + safetyResult: SafetyResult<*, *>, + inputFile: File, + property: ErrorDetection, + architecture: ArchitectureConfig.ArchitectureType?, + cexSolverFactory: SolverFactory, + parseContext: ParseContext, + witnessfile: File, + ) { + val metadata = + Metadata( + formatVersion = "2.0", + uuid = UUID.randomUUID().toString(), + creationTime = getIsoDate(), + producer = + Producer( + name = (System.getenv("VERIFIER_NAME") ?: "").ifEmpty { "Theta" }, + version = (System.getenv("VERIFIER_VERSION") ?: "").ifEmpty { "no version found" }, + ), + task = + Task( + inputFiles = listOf(inputFile.name), + inputFileHashes = listOf(createTaskHash(inputFile.path)), + specification = property.name, + dataModel = + architecture?.let { + if (it == ArchitectureConfig.ArchitectureType.ILP32) DataModel.ILP32 + else DataModel.LP64 + } ?: DataModel.ILP32, + language = Language.C, + ), + ) + + if (safetyResult.isUnsafe && safetyResult.asUnsafe().cex is Trace<*, *>) { + val concrTrace: Trace, XcfaAction> = + XcfaTraceConcretizer.concretize( + safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, + cexSolverFactory, + parseContext, ) - if (safetyResult.isUnsafe && safetyResult.asUnsafe().cex is Trace<*, *>) { - val concrTrace: Trace, XcfaAction> = XcfaTraceConcretizer.concretize( - safetyResult.asUnsafe().cex as Trace>, XcfaAction>?, cexSolverFactory, - parseContext) - - val witnessTrace = traceToWitness(trace = concrTrace, parseContext = parseContext) - - val witness = YamlWitness( - entryType = EntryType.VIOLATION, - metadata = metadata, - content = (0..(witnessTrace.length())).flatMap { - listOfNotNull( - witnessTrace.states.get(it)?.toSegment(witnessTrace.actions.getOrNull(it-1), inputFile), - witnessTrace.actions.getOrNull(it)?.toSegment(inputFile) - ) - } - ) + val witnessTrace = traceToWitness(trace = concrTrace, parseContext = parseContext) + + val witness = + YamlWitness( + entryType = EntryType.VIOLATION, + metadata = metadata, + content = + (0..(witnessTrace.length())).flatMap { + listOfNotNull( + witnessTrace.states + .get(it) + ?.toSegment(witnessTrace.actions.getOrNull(it - 1), inputFile), + witnessTrace.actions.getOrNull(it)?.toSegment(inputFile), + ) + }, + ) - witnessfile.writeText(WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness)) - } else if (safetyResult.isSafe) { + witnessfile.writeText(WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness)) + } else if (safetyResult.isSafe) { - val witness = YamlWitness( - entryType = EntryType.INVARIANTS, - metadata = metadata, - content = safetyResult.asSafe().proof.toContent(inputFile, parseContext) - ) + val witness = + YamlWitness( + entryType = EntryType.INVARIANTS, + metadata = metadata, + content = safetyResult.asSafe().proof.toContent(inputFile, parseContext), + ) - witnessfile.writeText(WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness)) - } + witnessfile.writeText(WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness)) } + } } private fun getLocation(inputFile: File, metadata: MetaData?): Location? { - val line = (metadata as? CMetaData)?.lineNumberStart ?: (metadata as? CMetaData)?.lineNumberStop ?: return null - val column = (metadata as? CMetaData)?.colNumberStart ?: (metadata as? CMetaData)?.colNumberStop - return Location( - fileName = inputFile.name, - line = line, - column = column, - ) + val line = + (metadata as? CMetaData)?.lineNumberStart + ?: (metadata as? CMetaData)?.lineNumberStop + ?: return null + val column = (metadata as? CMetaData)?.colNumberStart ?: (metadata as? CMetaData)?.colNumberStop + return Location(fileName = inputFile.name, line = line, column = column) } private fun getLocation(inputFile: File, witnessEdge: WitnessEdge?): Location? { - if(witnessEdge == null) return null - val endLoc = Location( - fileName = inputFile.name, - line = witnessEdge.endline ?: witnessEdge.startline ?: return null, - column = (witnessEdge.endcol ?: witnessEdge.startcol)?.plus(1), + if (witnessEdge == null) return null + val endLoc = + Location( + fileName = inputFile.name, + line = witnessEdge.endline ?: witnessEdge.startline ?: return null, + column = (witnessEdge.endcol ?: witnessEdge.startcol)?.plus(1), ) - return endLoc + return endLoc } private fun WitnessNode.toSegment(witnessEdge: WitnessEdge?, inputFile: File): ContentItem? { - if(violation) { - val loc = xcfaLocations.values.first().first() - val locLoc = getLocation(inputFile, loc.metadata) ?: getLocation(inputFile, witnessEdge) ?: getLocation(inputFile, witnessEdge?.edge?.metadata) ?: return null - return ContentItem(Segment( - Waypoint( - type = WaypointType.TARGET, - location = locLoc, - action = Action.FOLLOW - ) - )) - } else { - return null - } + if (violation) { + val loc = xcfaLocations.values.first().first() + val locLoc = + getLocation(inputFile, loc.metadata) + ?: getLocation(inputFile, witnessEdge) + ?: getLocation(inputFile, witnessEdge?.edge?.metadata) + ?: return null + return ContentItem( + Segment(Waypoint(type = WaypointType.TARGET, location = locLoc, action = Action.FOLLOW)) + ) + } else { + return null + } } private fun WitnessEdge.toSegment(inputFile: File): ContentItem? { - val endLoc = Location( - fileName = inputFile.name, - line = endline ?: startline ?: return null, - column = (endcol ?: startcol)?.plus(1), + val endLoc = + Location( + fileName = inputFile.name, + line = endline ?: startline ?: return null, + column = (endcol ?: startcol)?.plus(1), ) - val startLoc = Location( - fileName = inputFile.name, - line = startline ?: endline ?: return null, - column = (startcol ?: endcol)?.plus(1), + val startLoc = + Location( + fileName = inputFile.name, + line = startline ?: endline ?: return null, + column = (startcol ?: endcol)?.plus(1), ) - val (loc, constraint, type) = if(assumption != null) { - Triple(endLoc, Constraint(value = assumption, format = Format.C_EXPRESSION), WaypointType.ASSUMPTION) - } else if(control != null) { - Triple(startLoc, Constraint(value = control.toString()), WaypointType.BRANCHING) - } else if(enterLoopHead) { - Triple(startLoc, Constraint(value = "true"), WaypointType.BRANCHING) - } else if(enterFunction != null) { - Triple(startLoc, Constraint(value = enterFunction), WaypointType.FUNCTION_ENTER) - } else if(returnFromFunction != null) { - Triple(endLoc, Constraint(value = returnFromFunction), WaypointType.FUNCTION_RETURN) + val (loc, constraint, type) = + if (assumption != null) { + Triple( + endLoc, + Constraint(value = assumption, format = Format.C_EXPRESSION), + WaypointType.ASSUMPTION, + ) + } else if (control != null) { + Triple(startLoc, Constraint(value = control.toString()), WaypointType.BRANCHING) + } else if (enterLoopHead) { + Triple(startLoc, Constraint(value = "true"), WaypointType.BRANCHING) + } else if (enterFunction != null) { + Triple(startLoc, Constraint(value = enterFunction), WaypointType.FUNCTION_ENTER) + } else if (returnFromFunction != null) { + Triple(endLoc, Constraint(value = returnFromFunction), WaypointType.FUNCTION_RETURN) } else return null - return ContentItem(Segment( - Waypoint( - type = type, - constraint = constraint, - location = loc, - action = Action.FOLLOW - ) - )) + return ContentItem( + Segment(Waypoint(type = type, constraint = constraint, location = loc, action = Action.FOLLOW)) + ) } private fun Proof.toContent(inputFile: File, parseContext: ParseContext): List { - if(this is ARG<*, *>) { - val locMap = nodes.toList().mapNotNull { - it as ArgNode, XcfaAction> - val loc = it.state.processes.values.firstOrNull()?.locs?.peek() ?: return@mapNotNull null - val locLoc = Location( - fileName = inputFile.name, - line = (loc.metadata as? CMetaData)?.lineNumberStart ?: (loc.metadata as? CMetaData)?.lineNumberStop ?: return@mapNotNull null, - column = (loc.metadata as? CMetaData)?.colNumberStart ?: (loc.metadata as? CMetaData)?.colNumberStop, - ) - locLoc to it.state.sGlobal.toExpr() - }.groupBy{ it.first } - val invs = locMap.mapValues { entry -> ExprUtils.simplify(Or(entry.value.map { it.second })) }.map { - ContentItem( - invariant = Invariant( - type = InvariantType.LOCATION_INVARIANT, - location = it.key, - value = it.value.toC(parseContext), - format = Format.C_EXPRESSION - ) + if (this is ARG<*, *>) { + val locMap = + nodes + .toList() + .mapNotNull { + it as ArgNode, XcfaAction> + val loc = it.state.processes.values.firstOrNull()?.locs?.peek() ?: return@mapNotNull null + val locLoc = + Location( + fileName = inputFile.name, + line = + (loc.metadata as? CMetaData)?.lineNumberStart + ?: (loc.metadata as? CMetaData)?.lineNumberStop + ?: return@mapNotNull null, + column = + (loc.metadata as? CMetaData)?.colNumberStart + ?: (loc.metadata as? CMetaData)?.colNumberStop, ) + locLoc to it.state.sGlobal.toExpr() } - return invs - } - return listOf() -} \ No newline at end of file + .groupBy { it.first } + val invs = + locMap + .mapValues { entry -> ExprUtils.simplify(Or(entry.value.map { it.second })) } + .map { + ContentItem( + invariant = + Invariant( + type = InvariantType.LOCATION_INVARIANT, + location = it.key, + value = it.value.toC(parseContext), + format = Format.C_EXPRESSION, + ) + ) + } + return invs + } + return listOf() +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt index fcaf982dfb..e5f6748d54 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/CommonWitness.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.witnesses import hu.bme.mit.theta.analysis.Action @@ -32,87 +31,80 @@ import java.text.SimpleDateFormat import java.util.* data class WitnessNode( - val id: String, - val entry: Boolean = false, - val sink: Boolean = false, - val violation: Boolean = false, - - val xcfaLocations: Map> = emptyMap(), - val cSources: Map> = emptyMap(), - val globalState: ExplState? = null + val id: String, + val entry: Boolean = false, + val sink: Boolean = false, + val violation: Boolean = false, + val xcfaLocations: Map> = emptyMap(), + val cSources: Map> = emptyMap(), + val globalState: ExplState? = null, ) : State { - override fun isBottom(): Boolean { - error("Not applicable for witness states.") - } + override fun isBottom(): Boolean { + error("Not applicable for witness states.") + } } data class WitnessEdge( - val sourceId: String, - val targetId: String, - val assumption: String? = null, - val assumption_scope: String? = null, - val assumption_resultfunction: String? = null, - val control: Boolean? = null, - val startline: Int? = null, - val endline: Int? = null, - val startoffset: Int? = null, - val endoffset: Int? = null, - val startcol: Int? = null, - val endcol: Int? = null, - val enterLoopHead: Boolean = false, - val enterFunction: String? = null, - val returnFromFunction: String? = null, - val threadId: String? = null, - val createThread: String? = null, - - val stmt: String? = null, - val cSource: String? = null, - val edge: XcfaEdge? = null, -) : Action { -} + val sourceId: String, + val targetId: String, + val assumption: String? = null, + val assumption_scope: String? = null, + val assumption_resultfunction: String? = null, + val control: Boolean? = null, + val startline: Int? = null, + val endline: Int? = null, + val startoffset: Int? = null, + val endoffset: Int? = null, + val startcol: Int? = null, + val endcol: Int? = null, + val enterLoopHead: Boolean = false, + val enterFunction: String? = null, + val returnFromFunction: String? = null, + val threadId: String? = null, + val createThread: String? = null, + val stmt: String? = null, + val cSource: String? = null, + val edge: XcfaEdge? = null, +) : Action {} fun createTaskHash(programFile: String): String { - var md: MessageDigest? = null - try { - md = MessageDigest.getInstance("SHA-256") - } catch (e: NoSuchAlgorithmException) { - e.printStackTrace() - } - try { - Files.newInputStream(Paths.get(programFile)).use { `is` -> - DigestInputStream(`is`, md).use { dis -> - while (dis.read() != -1) { - } - } - } - } catch (e: IOException) { - e.printStackTrace() + var md: MessageDigest? = null + try { + md = MessageDigest.getInstance("SHA-256") + } catch (e: NoSuchAlgorithmException) { + e.printStackTrace() + } + try { + Files.newInputStream(Paths.get(programFile)).use { `is` -> + DigestInputStream(`is`, md).use { dis -> while (dis.read() != -1) {} } } - assert(md != null) - val digest = md!!.digest() - return bytesToHex(digest) + } catch (e: IOException) { + e.printStackTrace() + } + assert(md != null) + val digest = md!!.digest() + return bytesToHex(digest) } // source: https://www.baeldung.com/sha-256-hashing-java fun bytesToHex(hash: ByteArray): String { - val hexString = StringBuilder(2 * hash.size) - for (i in hash.indices) { - val hex = Integer.toHexString(0xff and hash[i].toInt()) - if (hex.length == 1) { - hexString.append('0') - } - hexString.append(hex) + val hexString = StringBuilder(2 * hash.size) + for (i in hash.indices) { + val hex = Integer.toHexString(0xff and hash[i].toInt()) + if (hex.length == 1) { + hexString.append('0') } - return hexString.toString() + hexString.append(hex) + } + return hexString.toString() } fun getIsoDate(): String { - val tz: TimeZone = TimeZone.getTimeZone("UTC") - val df: DateFormat = SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss'Z'" - ) // Quoted "Z" to indicate UTC, no timezone offset + val tz: TimeZone = TimeZone.getTimeZone("UTC") + val df: DateFormat = + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") // Quoted "Z" to indicate UTC, no timezone offset - df.timeZone = tz - return df.format(Date()) -} \ No newline at end of file + df.timeZone = tz + return df.format(Date()) +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt index d2906d7359..5d774f1d36 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/GraphmlWitness.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.witnesses import hu.bme.mit.theta.analysis.Trace @@ -28,63 +27,69 @@ import javax.xml.transform.TransformerFactory import javax.xml.transform.stream.StreamResult import javax.xml.transform.stream.StreamSource - class GraphmlWitness(private val trace: Trace, programFile: File) { - private val attributes: MutableList = ArrayList() - private val data: MutableList> = ArrayList() - - init { - attributes.add(GraphmlWitnessAttribute("sourcecodelang", "string", "graph", "sourcecodelang")) - attributes.add(GraphmlWitnessAttribute("creationtime", "string", "graph", "creationtime")) - attributes.add(GraphmlWitnessAttribute("witness-type", "string", "graph", "witness-type")) - attributes.add(GraphmlWitnessAttribute("producer", "string", "graph", "producer")) - attributes.add(GraphmlWitnessAttribute("architecture", "string", "graph", "architecture")) - attributes.add(GraphmlWitnessAttribute("programHash", "string", "graph", "programhash")) - attributes.add(GraphmlWitnessAttribute("programfile", "string", "graph", "programfile")) - attributes.add(GraphmlWitnessAttribute("specification", "string", "graph", "specification")) - - attributes.add(GraphmlWitnessAttribute("assumption", "string", "edge", "assumption")) - attributes.add(GraphmlWitnessAttribute("assumption.scope", "string", "edge", "assumption.scope")) - attributes.add( - GraphmlWitnessAttribute( - "assumption.resultfunction", "string", "edge", - "assumption.resultfunction")) - attributes.add(GraphmlWitnessAttribute("control", "string", "edge", "control")) - attributes.add(GraphmlWitnessAttribute("startline", "string", "edge", "startline")) - attributes.add(GraphmlWitnessAttribute("endline", "string", "edge", "endline")) - attributes.add(GraphmlWitnessAttribute("startoffset", "string", "edge", "startoffset")) - attributes.add(GraphmlWitnessAttribute("endoffset", "string", "edge", "endoffset")) - attributes.add(GraphmlWitnessAttribute("enterLoopHead", "string", "edge", "enterLoopHead")) - attributes.add(GraphmlWitnessAttribute("enterFunction", "string", "edge", "enterFunction")) - attributes.add( - GraphmlWitnessAttribute("returnFromFunction", "string", "edge", "returnFromFunction") - ) - attributes.add(GraphmlWitnessAttribute("threadId", "string", "edge", "threadId")) - attributes.add(GraphmlWitnessAttribute("createThread", "string", "edge", "createThread")) - attributes.add(GraphmlWitnessAttribute("stmt", "string", "edge", "stmt")) - attributes.add(GraphmlWitnessAttribute("cSource", "string", "edge", "cSource")) - - attributes.add(GraphmlWitnessAttribute("entry", "string", "node", "entry", "false")) - attributes.add(GraphmlWitnessAttribute("sink", "string", "node", "sink", "false")) - attributes.add(GraphmlWitnessAttribute("violation", "string", "node", "violation", "false")) - attributes.add(GraphmlWitnessAttribute("locationStacks", "string", "node", "locationStacks")) - attributes.add(GraphmlWitnessAttribute("sourceLines", "string", "node", "sourceLines")) - attributes.add(GraphmlWitnessAttribute("state", "string", "node", "state")) - - data.add(Pair("witness-type", "violation_witness")) - data.add(Pair("producer", "theta")) - data.add(Pair("sourcecodelang", "C")) - data.add(Pair("specification", "CHECK( init(main()), LTL(G ! call(reach_error())) )")) - data.add(Pair("programfile", programFile.absolutePath)) - data.add(Pair("programhash", createTaskHash(programFile.path))) - data.add(Pair("architecture", "32bit")) - data.add(Pair("creationtime", getIsoDate())) - } - - fun toPrettyXml(): String = prettyFormat(toXml(), 4) - - fun toXml(): String = """ + private val attributes: MutableList = ArrayList() + private val data: MutableList> = ArrayList() + + init { + attributes.add(GraphmlWitnessAttribute("sourcecodelang", "string", "graph", "sourcecodelang")) + attributes.add(GraphmlWitnessAttribute("creationtime", "string", "graph", "creationtime")) + attributes.add(GraphmlWitnessAttribute("witness-type", "string", "graph", "witness-type")) + attributes.add(GraphmlWitnessAttribute("producer", "string", "graph", "producer")) + attributes.add(GraphmlWitnessAttribute("architecture", "string", "graph", "architecture")) + attributes.add(GraphmlWitnessAttribute("programHash", "string", "graph", "programhash")) + attributes.add(GraphmlWitnessAttribute("programfile", "string", "graph", "programfile")) + attributes.add(GraphmlWitnessAttribute("specification", "string", "graph", "specification")) + + attributes.add(GraphmlWitnessAttribute("assumption", "string", "edge", "assumption")) + attributes.add( + GraphmlWitnessAttribute("assumption.scope", "string", "edge", "assumption.scope") + ) + attributes.add( + GraphmlWitnessAttribute( + "assumption.resultfunction", + "string", + "edge", + "assumption.resultfunction", + ) + ) + attributes.add(GraphmlWitnessAttribute("control", "string", "edge", "control")) + attributes.add(GraphmlWitnessAttribute("startline", "string", "edge", "startline")) + attributes.add(GraphmlWitnessAttribute("endline", "string", "edge", "endline")) + attributes.add(GraphmlWitnessAttribute("startoffset", "string", "edge", "startoffset")) + attributes.add(GraphmlWitnessAttribute("endoffset", "string", "edge", "endoffset")) + attributes.add(GraphmlWitnessAttribute("enterLoopHead", "string", "edge", "enterLoopHead")) + attributes.add(GraphmlWitnessAttribute("enterFunction", "string", "edge", "enterFunction")) + attributes.add( + GraphmlWitnessAttribute("returnFromFunction", "string", "edge", "returnFromFunction") + ) + attributes.add(GraphmlWitnessAttribute("threadId", "string", "edge", "threadId")) + attributes.add(GraphmlWitnessAttribute("createThread", "string", "edge", "createThread")) + attributes.add(GraphmlWitnessAttribute("stmt", "string", "edge", "stmt")) + attributes.add(GraphmlWitnessAttribute("cSource", "string", "edge", "cSource")) + + attributes.add(GraphmlWitnessAttribute("entry", "string", "node", "entry", "false")) + attributes.add(GraphmlWitnessAttribute("sink", "string", "node", "sink", "false")) + attributes.add(GraphmlWitnessAttribute("violation", "string", "node", "violation", "false")) + attributes.add(GraphmlWitnessAttribute("locationStacks", "string", "node", "locationStacks")) + attributes.add(GraphmlWitnessAttribute("sourceLines", "string", "node", "sourceLines")) + attributes.add(GraphmlWitnessAttribute("state", "string", "node", "state")) + + data.add(Pair("witness-type", "violation_witness")) + data.add(Pair("producer", "theta")) + data.add(Pair("sourcecodelang", "C")) + data.add(Pair("specification", "CHECK( init(main()), LTL(G ! call(reach_error())) )")) + data.add(Pair("programfile", programFile.absolutePath)) + data.add(Pair("programhash", createTaskHash(programFile.path))) + data.add(Pair("architecture", "32bit")) + data.add(Pair("creationtime", getIsoDate())) + } + + fun toPrettyXml(): String = prettyFormat(toXml(), 4) + + fun toXml(): String = + """ @@ -100,19 +105,20 @@ ${trace.actions.map(WitnessEdge::toXml).reduce { a, b -> "$a\n$b" }} - """.trimIndent() - + """ + .trimIndent() } data class GraphmlWitnessAttribute( - val name: String, - val type: String, - val `for`: String, - val id: String, - val defaultValue: String? = null + val name: String, + val type: String, + val `for`: String, + val id: String, + val defaultValue: String? = null, ) { - fun toXml(): String = """ + fun toXml(): String = + """ """.trimIndent() } -""".trimIndent() +""" + .trimIndent() } private fun escapeXml(toEscape: String): String { - var toEscape = toEscape - toEscape = toEscape.replace("&", "&") - toEscape = toEscape.replace("\"", """) - toEscape = toEscape.replace("'", "'") - toEscape = toEscape.replace("<", "<") - toEscape = toEscape.replace(">", ">") - return toEscape + var toEscape = toEscape + toEscape = toEscape.replace("&", "&") + toEscape = toEscape.replace("\"", """) + toEscape = toEscape.replace("'", "'") + toEscape = toEscape.replace("<", "<") + toEscape = toEscape.replace(">", ">") + return toEscape } // from https://stackoverflow.com/a/1264912 private fun prettyFormat(input: String, indent: Int): String { - return try { - val xmlInput: Source = StreamSource( - StringReader(input.replace(Regex("( )|[\\t\\n\\r]"), ""))) - val stringWriter = StringWriter() - val xmlOutput = StreamResult(stringWriter) - val transformerFactory: TransformerFactory = TransformerFactory.newInstance() - transformerFactory.setAttribute("indent-number", indent) - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") - transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "") - val transformer: Transformer = transformerFactory.newTransformer() - transformer.setOutputProperty(OutputKeys.INDENT, "yes") - transformer.transform(xmlInput, xmlOutput) - xmlOutput.getWriter().toString() - } catch (e: Exception) { - System.err.println(input.replace(Regex("( )|[\\t\\n\\r]"), "")) - throw RuntimeException(e) - } + return try { + val xmlInput: Source = StreamSource(StringReader(input.replace(Regex("( )|[\\t\\n\\r]"), ""))) + val stringWriter = StringWriter() + val xmlOutput = StreamResult(stringWriter) + val transformerFactory: TransformerFactory = TransformerFactory.newInstance() + transformerFactory.setAttribute("indent-number", indent) + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "") + val transformer: Transformer = transformerFactory.newTransformer() + transformer.setOutputProperty(OutputKeys.INDENT, "yes") + transformer.transform(xmlInput, xmlOutput) + xmlOutput.getWriter().toString() + } catch (e: Exception) { + System.err.println(input.replace(Regex("( )|[\\t\\n\\r]"), "")) + throw RuntimeException(e) + } } -fun WitnessNode.toXml(): String = """ +fun WitnessNode.toXml(): String = + """ ${if (entry) "true" else ""} ${if (sink) "true" else ""} @@ -178,9 +185,11 @@ fun WitnessNode.toXml(): String = """ }" else "" } - """.trimIndent() + """ + .trimIndent() -fun WitnessEdge.toXml(): String = """ +fun WitnessEdge.toXml(): String = + """ ${if (assumption != null) "$assumption" else ""} ${if (assumption_scope != null) "$assumption_scope" else ""} @@ -204,4 +213,5 @@ fun WitnessEdge.toXml(): String = """ } - """.trimIndent() \ No newline at end of file + """ + .trimIndent() diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt index 252e248e45..48c1ea369b 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/TraceToWitness.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.witnesses import com.google.common.collect.Lists @@ -32,185 +31,209 @@ import hu.bme.mit.theta.xcfa.model.* import java.math.BigInteger enum class Verbosity { - NECESSARY, - SOURCE_EXISTS, - STMT_EXISTS, - EVERYTHING + NECESSARY, + SOURCE_EXISTS, + STMT_EXISTS, + EVERYTHING, } fun traceToWitness( - verbosity: Verbosity = Verbosity.SOURCE_EXISTS, - trace: Trace, XcfaAction>, - parseContext: ParseContext + verbosity: Verbosity = Verbosity.SOURCE_EXISTS, + trace: Trace, XcfaAction>, + parseContext: ParseContext, ): Trace { - val newStates = ArrayList() - val newActions = ArrayList() - - var lastNode = WitnessNode(id = "N${newStates.size}", entry = true, sink = false, - violation = false) - newStates.add(lastNode) - - for (i in 0 until trace.length()) { - val state = trace.states[i] - val action = trace.actions[i] - val nextState = trace.states[i + 1] - val newThreads = nextState.processes.keys - state.processes.keys - val node = WitnessNode( - id = "N${newStates.size}", - entry = false, - sink = false, - violation = state.processes.any { it.value.locs.any(XcfaLocation::error) }, - xcfaLocations = state.processes.map { Pair(it.key, it.value.locs) }.toMap(), - cSources = state.processes.map { - Pair(it.key, it.value.locs.map { it.getCMetaData()?.sourceText ?: "" }) - }.toMap(), - globalState = state.sGlobal - ) - if (node != WitnessNode(id = "N${newStates.size}")) { - newStates.add(node) - val edge = WitnessEdge(sourceId = lastNode.id, targetId = node.id, - threadId = trace.actions[i].pid.toString(), edge = action.edge - ) - newActions.add(edge) - lastNode = node - } - - val flattenedSequence = flattenSequence(action.edge.label) - for (xcfaLabel in flattenedSequence) { - val node = WitnessNode(id = "N${newStates.size}", entry = false, sink = false, - violation = false) - var edge = labelToEdge(lastNode, node, xcfaLabel, action.pid, - nextState.sGlobal.getVal(), parseContext, action.edge - ) - if (newThreads.isNotEmpty() && xcfaLabel is StartLabel) { - edge = edge.copy(createThread = newThreads.joinToString(",")) - } - if (node != WitnessNode(id = "N${newStates.size}") || shouldInclude(edge, verbosity)) { - newStates.add(node) - newActions.add(edge) - lastNode = node - } - } - } - - val lastState = trace.states[trace.length()] - val node = WitnessNode( + val newStates = ArrayList() + val newActions = ArrayList() + + var lastNode = + WitnessNode(id = "N${newStates.size}", entry = true, sink = false, violation = false) + newStates.add(lastNode) + + for (i in 0 until trace.length()) { + val state = trace.states[i] + val action = trace.actions[i] + val nextState = trace.states[i + 1] + val newThreads = nextState.processes.keys - state.processes.keys + val node = + WitnessNode( id = "N${newStates.size}", entry = false, sink = false, - violation = lastState.processes.any { it.value.locs.any(XcfaLocation::error) }, - xcfaLocations = lastState.processes.map { Pair(it.key, it.value.locs) }.toMap(), - cSources = lastState.processes.map { - Pair(it.key, it.value.locs.map { it.getCMetaData()?.sourceText ?: "" }) - }.toMap(), - globalState = lastState.sGlobal - ) - newStates.add(node) - val edge = WitnessEdge(sourceId = lastNode.id, targetId = node.id, edge = trace.actions[trace.length() - 1].edge) - newActions.add(edge) + violation = state.processes.any { it.value.locs.any(XcfaLocation::error) }, + xcfaLocations = state.processes.map { Pair(it.key, it.value.locs) }.toMap(), + cSources = + state.processes + .map { + Pair(it.key, it.value.locs.map { it.getCMetaData()?.sourceText ?: "" }) + } + .toMap(), + globalState = state.sGlobal, + ) + if (node != WitnessNode(id = "N${newStates.size}")) { + newStates.add(node) + val edge = + WitnessEdge( + sourceId = lastNode.id, + targetId = node.id, + threadId = trace.actions[i].pid.toString(), + edge = action.edge, + ) + newActions.add(edge) + lastNode = node + } - return Trace.of(newStates, newActions) + val flattenedSequence = flattenSequence(action.edge.label) + for (xcfaLabel in flattenedSequence) { + val node = + WitnessNode(id = "N${newStates.size}", entry = false, sink = false, violation = false) + var edge = + labelToEdge( + lastNode, + node, + xcfaLabel, + action.pid, + nextState.sGlobal.getVal(), + parseContext, + action.edge, + ) + if (newThreads.isNotEmpty() && xcfaLabel is StartLabel) { + edge = edge.copy(createThread = newThreads.joinToString(",")) + } + if (node != WitnessNode(id = "N${newStates.size}") || shouldInclude(edge, verbosity)) { + newStates.add(node) + newActions.add(edge) + lastNode = node + } + } + } + + val lastState = trace.states[trace.length()] + val node = + WitnessNode( + id = "N${newStates.size}", + entry = false, + sink = false, + violation = lastState.processes.any { it.value.locs.any(XcfaLocation::error) }, + xcfaLocations = lastState.processes.map { Pair(it.key, it.value.locs) }.toMap(), + cSources = + lastState.processes + .map { Pair(it.key, it.value.locs.map { it.getCMetaData()?.sourceText ?: "" }) } + .toMap(), + globalState = lastState.sGlobal, + ) + newStates.add(node) + val edge = + WitnessEdge( + sourceId = lastNode.id, + targetId = node.id, + edge = trace.actions[trace.length() - 1].edge, + ) + newActions.add(edge) + return Trace.of(newStates, newActions) } fun shouldInclude(edge: WitnessEdge, verbosity: Verbosity): Boolean = - when (verbosity) { - Verbosity.NECESSARY -> edge.control != null || edge.assumption != null || edge.createThread != null - Verbosity.SOURCE_EXISTS -> shouldInclude(edge, Verbosity.NECESSARY) || edge.cSource != null - Verbosity.STMT_EXISTS -> shouldInclude(edge, Verbosity.NECESSARY) || edge.stmt != null - Verbosity.EVERYTHING -> true - } - + when (verbosity) { + Verbosity.NECESSARY -> + edge.control != null || edge.assumption != null || edge.createThread != null + Verbosity.SOURCE_EXISTS -> shouldInclude(edge, Verbosity.NECESSARY) || edge.cSource != null + Verbosity.STMT_EXISTS -> shouldInclude(edge, Verbosity.NECESSARY) || edge.stmt != null + Verbosity.EVERYTHING -> true + } private fun labelToEdge( - lastNode: WitnessNode, node: WitnessNode, xcfaLabel: XcfaLabel, pid: Int, - valuation: Valuation, parseContext: ParseContext, edge: XcfaEdge + lastNode: WitnessNode, + node: WitnessNode, + xcfaLabel: XcfaLabel, + pid: Int, + valuation: Valuation, + parseContext: ParseContext, + edge: XcfaEdge, ): WitnessEdge = - WitnessEdge( - sourceId = lastNode.id, - targetId = node.id, - - assumption = if (xcfaLabel is StmtLabel && xcfaLabel.stmt is HavocStmt<*>) { - val varDecl = (xcfaLabel.stmt as HavocStmt<*>).varDecl - val eval = valuation.eval(varDecl) - val splitName = varDecl.name.split("::") - val rootName = if (splitName[0].matches(Regex("T[0-9]*"))) splitName.subList(2, splitName.size) - .joinToString("::") else varDecl.name - if (parseContext.metadata.getMetadataValue(rootName, "cName").isPresent && eval.isPresent) - "${parseContext.metadata.getMetadataValue(rootName, "cName").get()} == ${ + WitnessEdge( + sourceId = lastNode.id, + targetId = node.id, + assumption = + if (xcfaLabel is StmtLabel && xcfaLabel.stmt is HavocStmt<*>) { + val varDecl = (xcfaLabel.stmt as HavocStmt<*>).varDecl + val eval = valuation.eval(varDecl) + val splitName = varDecl.name.split("::") + val rootName = + if (splitName[0].matches(Regex("T[0-9]*"))) + splitName.subList(2, splitName.size).joinToString("::") + else varDecl.name + if (parseContext.metadata.getMetadataValue(rootName, "cName").isPresent && eval.isPresent) + "${parseContext.metadata.getMetadataValue(rootName, "cName").get()} == ${ printLit(eval.get()) }" - else null - } else null, - - control = if (xcfaLabel is StmtLabel && xcfaLabel.choiceType != ChoiceType.NONE) { - xcfaLabel.choiceType == ChoiceType.MAIN_PATH - } else null, - - startline = xcfaLabel.getCMetaData()?.lineNumberStart, - endline = xcfaLabel.getCMetaData()?.lineNumberStop, - startoffset = xcfaLabel.getCMetaData()?.offsetStart, - endoffset = xcfaLabel.getCMetaData()?.offsetEnd, - startcol = xcfaLabel.getCMetaData()?.colNumberStart, - endcol = xcfaLabel.getCMetaData()?.colNumberStop, - - threadId = if (pid != null) "$pid" else null, - - stmt = if (xcfaLabel is StmtLabel) xcfaLabel.stmt.toString() else null, - cSource = xcfaLabel.getCMetaData()?.sourceText, - edge = edge - ) + else null + } else null, + control = + if (xcfaLabel is StmtLabel && xcfaLabel.choiceType != ChoiceType.NONE) { + xcfaLabel.choiceType == ChoiceType.MAIN_PATH + } else null, + startline = xcfaLabel.getCMetaData()?.lineNumberStart, + endline = xcfaLabel.getCMetaData()?.lineNumberStop, + startoffset = xcfaLabel.getCMetaData()?.offsetStart, + endoffset = xcfaLabel.getCMetaData()?.offsetEnd, + startcol = xcfaLabel.getCMetaData()?.colNumberStart, + endcol = xcfaLabel.getCMetaData()?.colNumberStop, + threadId = if (pid != null) "$pid" else null, + stmt = if (xcfaLabel is StmtLabel) xcfaLabel.stmt.toString() else null, + cSource = xcfaLabel.getCMetaData()?.sourceText, + edge = edge, + ) private fun flattenSequence(label: XcfaLabel): List = - when (label) { - is NondetLabel -> error("Cannot handle nondet labels in witnesses") - is SequenceLabel -> label.labels.map { flattenSequence(it) }.flatten() - else -> listOf(label) - } + when (label) { + is NondetLabel -> error("Cannot handle nondet labels in witnesses") + is SequenceLabel -> label.labels.map { flattenSequence(it) }.flatten() + else -> listOf(label) + } private fun printLit(litExpr: LitExpr<*>): String? { - return if (litExpr is BvLitExpr) { - val value = litExpr.value - var intValue = BigInteger.ZERO - for (i in value.indices) { - val b = value[i] - if (b) { - intValue = intValue.add(BigInteger.ONE.shiftLeft(value.size - 1 - i)) - } - } - "0x" + intValue.toString(16) - } else if (litExpr is FpLitExpr) { - val boolList: MutableList = java.util.ArrayList() - val tmpList: MutableList = java.util.ArrayList() - for (b in litExpr.significand.value) { - tmpList.add(b) - } - boolList.addAll(Lists.reverse(tmpList)) - tmpList.clear() - for (b in litExpr.exponent.value) { - tmpList.add(b) - } - boolList.addAll(Lists.reverse(tmpList)) - boolList.add(litExpr.hidden) - var aggregate = 0 - val hexDigits: MutableList = java.util.ArrayList() - for (i in boolList.indices) { - if (i % 4 == 0 && i > 0) { - if (aggregate < 10) hexDigits.add( - ('0'.code + aggregate).toChar()) else hexDigits.add( - ('A'.code - 10 + aggregate).toChar()) - aggregate = 0 - } - if (boolList[i]) aggregate += 1 shl i % 4 - } - if (aggregate < 10) hexDigits.add(('0'.code + aggregate).toChar()) else hexDigits.add( - ('A'.code - 10 + aggregate).toChar()) - val stringBuilder = StringBuilder("0x") - for (character in Lists.reverse(hexDigits)) { - stringBuilder.append(character) - } - stringBuilder.toString() - } else { - litExpr.toString() + return if (litExpr is BvLitExpr) { + val value = litExpr.value + var intValue = BigInteger.ZERO + for (i in value.indices) { + val b = value[i] + if (b) { + intValue = intValue.add(BigInteger.ONE.shiftLeft(value.size - 1 - i)) + } + } + "0x" + intValue.toString(16) + } else if (litExpr is FpLitExpr) { + val boolList: MutableList = java.util.ArrayList() + val tmpList: MutableList = java.util.ArrayList() + for (b in litExpr.significand.value) { + tmpList.add(b) } -} \ No newline at end of file + boolList.addAll(Lists.reverse(tmpList)) + tmpList.clear() + for (b in litExpr.exponent.value) { + tmpList.add(b) + } + boolList.addAll(Lists.reverse(tmpList)) + boolList.add(litExpr.hidden) + var aggregate = 0 + val hexDigits: MutableList = java.util.ArrayList() + for (i in boolList.indices) { + if (i % 4 == 0 && i > 0) { + if (aggregate < 10) hexDigits.add(('0'.code + aggregate).toChar()) + else hexDigits.add(('A'.code - 10 + aggregate).toChar()) + aggregate = 0 + } + if (boolList[i]) aggregate += 1 shl i % 4 + } + if (aggregate < 10) hexDigits.add(('0'.code + aggregate).toChar()) + else hexDigits.add(('A'.code - 10 + aggregate).toChar()) + val stringBuilder = StringBuilder("0x") + for (character in Lists.reverse(hexDigits)) { + stringBuilder.append(character) + } + stringBuilder.toString() + } else { + litExpr.toString() + } +} diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java index 435e3dbf9e..ab8faa04bd 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/XcfaTraceConcretizer.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.witnesses; +import static com.google.common.base.Preconditions.checkArgument; + import hu.bme.mit.theta.analysis.Action; import hu.bme.mit.theta.analysis.Trace; import hu.bme.mit.theta.analysis.expl.ExplState; @@ -39,20 +40,19 @@ import hu.bme.mit.theta.xcfa.analysis.XcfaAction; import hu.bme.mit.theta.xcfa.analysis.XcfaState; import hu.bme.mit.theta.xcfa.model.XcfaEdge; -import kotlin.Triple; - import java.util.*; import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkArgument; +import kotlin.Triple; /** - * Similar to CfaTraceConcretizer - * Takes a trace given by an unsafe result and uses and SMT solver to output a concrete counterexample + * Similar to CfaTraceConcretizer Takes a trace given by an unsafe result and uses and SMT solver to + * output a concrete counterexample */ public class XcfaTraceConcretizer { public static Trace, XcfaAction> concretize( - final Trace>, XcfaAction> trace, SolverFactory solverFactory, ParseContext parseContext) { + final Trace>, XcfaAction> trace, + SolverFactory solverFactory, + ParseContext parseContext) { List>> sbeStates = new ArrayList<>(); List sbeActions = new ArrayList<>(); @@ -60,15 +60,26 @@ public static Trace, XcfaAction> concretize( Map, Expr, Expr>>> nextW = Collections.emptyMap(); for (int i = 0; i < trace.getActions().size(); ++i) { - final XcfaEdge edge = new XcfaEdge(trace.getAction(i).getSource(), trace.getAction(i).getTarget(), trace.getAction(i).getLabel(), trace.getAction(i).getEdge().getMetadata()); - final XcfaAction action = new XcfaAction(trace.getAction(i).getPid(), edge, nextW, trace.getAction(i).getInCnt()); + final XcfaEdge edge = + new XcfaEdge( + trace.getAction(i).getSource(), + trace.getAction(i).getTarget(), + trace.getAction(i).getLabel(), + trace.getAction(i).getEdge().getMetadata()); + final XcfaAction action = + new XcfaAction( + trace.getAction(i).getPid(), + edge, + nextW, + trace.getAction(i).getInCnt()); sbeActions.add(action); nextW = action.nextWriteTriples(); sbeStates.add(trace.getState(i + 1).withState(new PtrState<>(ExplState.top()))); } Trace, XcfaAction> sbeTrace = Trace.of(sbeStates, sbeActions); - final ExprTraceChecker checker = ExprTraceFwBinItpChecker.create(BoolExprs.True(), - BoolExprs.True(), solverFactory.createItpSolver()); + final ExprTraceChecker checker = + ExprTraceFwBinItpChecker.create( + BoolExprs.True(), BoolExprs.True(), solverFactory.createItpSolver()); final ExprTraceStatus status = checker.check(sbeTrace); checkArgument(status.isFeasible(), "Infeasible trace."); final Trace valuations = status.asFeasible().getValuations(); @@ -78,7 +89,19 @@ public static Trace, XcfaAction> concretize( final List> cfaStates = new ArrayList<>(); final Set> varSoFar = new LinkedHashSet<>(); for (int i = 0; i < sbeTrace.getStates().size(); ++i) { - cfaStates.add(new XcfaState<>(null, sbeTrace.getState(i).getProcesses(), ExplState.of(ImmutableValuation.from(valuations.getState(i).toMap().entrySet().stream().filter(it -> varSoFar.contains(it.getKey())).collect(Collectors.toMap(Map.Entry, LitExpr>::getKey, Map.Entry::getValue)))))); + cfaStates.add( + new XcfaState<>( + null, + sbeTrace.getState(i).getProcesses(), + ExplState.of( + ImmutableValuation.from( + valuations.getState(i).toMap().entrySet().stream() + .filter(it -> varSoFar.contains(it.getKey())) + .collect( + Collectors.toMap( + Map.Entry, LitExpr> + ::getKey, + Map.Entry::getValue)))))); if (i < sbeTrace.getActions().size()) { varSoFar.addAll(ExprUtils.getVars(sbeTrace.getAction(i).toExpr())); } @@ -86,5 +109,4 @@ public static Trace, XcfaAction> concretize( return Trace.of(cfaStates, sbeActions); } - } diff --git a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt index b3c000f5ad..15fa63eada 100644 --- a/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt +++ b/subprojects/xcfa/xcfa-cli/src/main/java/hu/bme/mit/theta/xcfa/cli/witnesses/YamlWitness.kt @@ -13,248 +13,289 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli.witnesses import com.charleskorn.kaml.Yaml import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -val WitnessYamlConfig = Yaml(configuration = Yaml.default.configuration.copy(encodeDefaults = false)) +val WitnessYamlConfig = + Yaml(configuration = Yaml.default.configuration.copy(encodeDefaults = false)) // https://gitlab.com/sosy-lab/benchmarking/sv-witnesses/-/blob/8f5dc4bf00c01bc6d5636d7993e164d181e19204/violation-witness-schema.yml // https://gitlab.com/sosy-lab/benchmarking/sv-witnesses/-/blob/8f5dc4bf00c01bc6d5636d7993e164d181e19204/correctness-witness-schema.yml /** - * For violations: - * Each entry consists of three key-value pairs, namely the key `entry_type` with value `violation_sequence`, - * the key metadata, and the key content. - * For correctness: - * The `entry_type` defines what content is available in the content field. The only allowed entry type for a correctness witness is `invariant_set`. - * @param entryType The `entry_type` defines what content is available in the content field. The only allowed entry type for a correctness witness is `violation_sequence`. - * @param metadata The meta data describe the provenance of the data. - * @param content For violations: The content represents the semantical content of the violation witness. It is a sequence of one or more segments. The content contains a sequence of zero or more normal segments and exactly one final segment at the end. - * For correctness: The content represents the semantical content of the correctness witness. It is a sequence of one or more invariant elements. + * For violations: Each entry consists of three key-value pairs, namely the key `entry_type` with + * value `violation_sequence`, the key metadata, and the key content. For correctness: The + * `entry_type` defines what content is available in the content field. The only allowed entry type + * for a correctness witness is `invariant_set`. * + * @param entryType The `entry_type` defines what content is available in the content field. The + * only allowed entry type for a correctness witness is `violation_sequence`. + * @param metadata The meta data describe the provenance of the data. + * @param content For violations: The content represents the semantical content of the violation + * witness. It is a sequence of one or more segments. The content contains a sequence of zero or + * more normal segments and exactly one final segment at the end. For correctness: The content + * represents the semantical content of the correctness witness. It is a sequence of one or more + * invariant elements. */ -@Serializable data class YamlWitness( - @SerialName("entry_type") - val entryType: EntryType, - val metadata: Metadata, - val content: List, +@Serializable +data class YamlWitness( + @SerialName("entry_type") val entryType: EntryType, + val metadata: Metadata, + val content: List, ) -@Serializable enum class EntryType { - @SerialName("violation_sequence") VIOLATION, - @SerialName("invariant_set") INVARIANTS, +@Serializable +enum class EntryType { + @SerialName("violation_sequence") VIOLATION, + @SerialName("invariant_set") INVARIANTS, } /** * The meta data describe the provenance of the data. - * @param formatVersion The `version` of the format is given as a string (currently "2.0"). - * @param uuid The `uuid` is a unique identifier of the entry; it uses the UUID format defined in RFC4122. - * @param creationTime The `creation_time` describes the date and time when the entry was created; it uses the format given by ISO 8601. - * @param producer The key `producer` describes the tool that produced the entry. * + * @param formatVersion The `version` of the format is given as a string (currently "2.0"). + * @param uuid The `uuid` is a unique identifier of the entry; it uses the UUID format defined in + * RFC4122. + * @param creationTime The `creation_time` describes the date and time when the entry was created; + * it uses the format given by ISO 8601. + * @param producer The key `producer` describes the tool that produced the entry. */ -@Serializable data class Metadata( - @SerialName("format_version") - val formatVersion: String, - val uuid: String, - @SerialName("creation_time") - val creationTime: String, - val producer: Producer, - val task: Task, +@Serializable +data class Metadata( + @SerialName("format_version") val formatVersion: String, + val uuid: String, + @SerialName("creation_time") val creationTime: String, + val producer: Producer, + val task: Task, ) /** * The key `producer` describes the tool that produced the entry. + * * @param name The name of the tool that produced the witness. * @param version The version of the tool * @param configuration The configuration in which the tool ran (optional) - * @param commandLine The command line with which the tool ran; it should be a bash-compliant command (optional) + * @param commandLine The command line with which the tool ran; it should be a bash-compliant + * command (optional) * @param description Any information not fitting in the previous items (optional) */ -@Serializable data class Producer( - val name: String, - val version: String, - val configuration: String? = null, - @SerialName("command_line") - val commandLine: String? = null, - val description: String? = null, +@Serializable +data class Producer( + val name: String, + val version: String, + val configuration: String? = null, + @SerialName("command_line") val commandLine: String? = null, + val description: String? = null, ) /** * The task describes the verification task to which the entry is related. - * @param inputFiles The list of files given as input to the verifier, e.g. ["path/f1.c", "path/f2.c"]. - * @param inputFileHashes The SHA-256 hashes of all files in input_files, e.g. {"path/f1.c": 511..., "path/f2.c": f70...} - * @param specification The specification considered by the verifier; it uses the SV-COMP format given at https://sv-comp.sosy-lab.org/2023/rules.php. + * + * @param inputFiles The list of files given as input to the verifier, e.g. + * ["path/f1.c", "path/f2.c"]. + * @param inputFileHashes The SHA-256 hashes of all files in input_files, e.g. {"path/f1.c": 511..., + * "path/f2.c": f70...} + * @param specification The specification considered by the verifier; it uses the SV-COMP format + * given at https://sv-comp.sosy-lab.org/2023/rules.php. * @param dataModel The data model assumed for the input program. (ILP32 / LP64) - * @param language The programming language of the input files; the format currently supports only C. + * @param language The programming language of the input files; the format currently supports only + * C. */ -@Serializable data class Task( - @SerialName("input_files") - val inputFiles: List, - @SerialName("input_file_hashes") - val inputFileHashes: List, - val specification: String, - @SerialName("data_model") - val dataModel: DataModel, - val language: Language, +@Serializable +data class Task( + @SerialName("input_files") val inputFiles: List, + @SerialName("input_file_hashes") val inputFileHashes: List, + val specification: String, + @SerialName("data_model") val dataModel: DataModel, + val language: Language, ) -@Serializable enum class DataModel { - ILP32, - LP64, +@Serializable +enum class DataModel { + ILP32, + LP64, } -@Serializable enum class Language { - C +@Serializable +enum class Language { + C } /** - * @param segment A `segment` is a sequence of one or more waypoints. They are used to structure the waypoints into segments. Each `segment` is a sequence of zero or more waypoints with action `avoid` and exactly one waypoint of action `follow` at the end. A segment is called _final_ if it ends with the `target` waypoint and it is called _normal_ otherwise. items: type: object required: - waypoint properties: waypoint: type: object required: - type - action - location description: | The `waypoint` elements are the basic building block of violation witnesses. They have the form of simple restrictions on program executions. Technically, a waypoint is a mapping with four keys, namely type, location, constraint, and action. The values of the first three keys specify the requirement on a program execution to pass a waypoint: `type` describes the type of the requirement, `location` specifies the program location where the requirement is evaluated, and `constraint` gives the requirement itself and is not allowed for waypoints of type `function_enter` and `target`. The key `action` then states whether the executions represented by the witness should pass through the waypoint (value `follow`) or avoid it (value `avoid`). The format currently supports two possible values of type with the following meanings: - `assumption`: The location has to point to the beginning of a statement or a declaration inside a compound statement. A requirement of this type says that a given constraint is satisfied before the pointed statement or declaration inside a compound statement. The constraint is a mapping with two keys: `format` specifies the language of the assumption and `value` contains a side-effect-free assumption over variables in the current scope. The value of `format` is `c_expression` as C expressions are the only assumptions currently supported. In future, we plan to support also assumptions in ACSL. - `target`: This type of requirement can be used only with action `follow` and it marks the program location where the property is violated. More precisely, the location points at the first character of the statement or full expression whose evaluation is sequenced directly before the violation occurs, i.e., there is no other evaluation sequenced before the violation and the sequence point associated with the location. This also implies that it can only point to a function call if it calls a function of the C standard library - * @param invariant The key `invariant` is the basic building block of correctness witnesses. It is a mapping that describes one invariant. + * @param segment A `segment` is a sequence of one or more waypoints. They are used to structure the + * waypoints into segments. Each `segment` is a sequence of zero or more waypoints with action + * `avoid` and exactly one waypoint of action `follow` at the end. A segment is called _final_ if + * it ends with the `target` waypoint and it is called _normal_ otherwise. items: type: object + * required: - waypoint properties: waypoint: type: object required: - type - action - location + * description: | The `waypoint` elements are the basic building block of violation witnesses. + * They have the form of simple restrictions on program executions. Technically, a waypoint is a + * mapping with four keys, namely type, location, constraint, and action. The values of the first + * three keys specify the requirement on a program execution to pass a waypoint: `type` describes + * the type of the requirement, `location` specifies the program location where the requirement is + * evaluated, and `constraint` gives the requirement itself and is not allowed for waypoints of + * type `function_enter` and `target`. The key `action` then states whether the executions + * represented by the witness should pass through the waypoint (value `follow`) or avoid it (value + * `avoid`). The format currently supports two possible values of type with the following + * meanings: - `assumption`: The location has to point to the beginning of a statement or a + * declaration inside a compound statement. A requirement of this type says that a given + * constraint is satisfied before the pointed statement or declaration inside a compound + * statement. The constraint is a mapping with two keys: `format` specifies the language of the + * assumption and `value` contains a side-effect-free assumption over variables in the current + * scope. The value of `format` is `c_expression` as C expressions are the only assumptions + * currently supported. In future, we plan to support also assumptions in ACSL. - `target`: This + * type of requirement can be used only with action `follow` and it marks the program location + * where the property is violated. More precisely, the location points at the first character of + * the statement or full expression whose evaluation is sequenced directly before the violation + * occurs, i.e., there is no other evaluation sequenced before the violation and the sequence + * point associated with the location. This also implies that it can only point to a function call + * if it calls a function of the C standard library + * @param invariant The key `invariant` is the basic building block of correctness witnesses. It is + * a mapping that describes one invariant. */ -@Serializable data class ContentItem( - val segment: Segment? = null, - val invariant: Invariant? = null, -) +@Serializable +data class ContentItem(val segment: Segment? = null, val invariant: Invariant? = null) -@Serializable data class Segment( - val waypoint: Waypoint, -) +@Serializable data class Segment(val waypoint: Waypoint) /** - * The `waypoint` elements are the basic building block of violation witnesses. - * They have the form of simple restrictions on program executions. - * Technically, a waypoint is a mapping with four keys, namely type, location, constraint, and action. - * The values of the first three keys specify the requirement on a program execution to pass a waypoint: - * `type` describes the type of the requirement, - * `location` specifies the program location where the requirement is evaluated, and - * `constraint` gives the requirement itself and is not allowed for waypoints of type `function_enter` and `target`. - * The key `action` then states whether the executions represented by the witness should - * pass through the waypoint (value `follow`) or avoid it (value `avoid`). - * The format currently supports two possible values of type with the following meanings: + * The `waypoint` elements are the basic building block of violation witnesses. They have the form + * of simple restrictions on program executions. Technically, a waypoint is a mapping with four + * keys, namely type, location, constraint, and action. The values of the first three keys specify + * the requirement on a program execution to pass a waypoint: `type` describes the type of the + * requirement, `location` specifies the program location where the requirement is evaluated, and + * `constraint` gives the requirement itself and is not allowed for waypoints of type + * `function_enter` and `target`. The key `action` then states whether the executions represented by + * the witness should pass through the waypoint (value `follow`) or avoid it (value `avoid`). The + * format currently supports two possible values of type with the following meanings: + * - `assumption`: The location has to point to the beginning of a statement or a declaration inside + * a compound statement. A requirement of this type says that a given constraint is satisfied + * before the pointed statement or declaration inside a compound statement. The constraint is a + * mapping with two keys: `format` specifies the language of the assumption and `value` contains a + * side-effect-free assumption over variables in the current scope. The value of `format` is + * `c_expression` as C expressions are the only assumptions currently supported. In future, we + * plan to support also assumptions in ACSL. + * - `target`: This type of requirement can be used only with action `follow` and it marks the + * program location where the property is violated. More precisely, the location points at the + * first character of the statement or full expression whose evaluation is sequenced directly + * before the violation occurs, i.e., there is no other evaluation sequenced before the violation + * and the sequence point associated with the location. This also implies that it can only point + * to a function call if it calls a function of the C standard library that violates the property + * or if the function call itself is the property violation. The key constraint has to be omitted + * for type `target`. + * - `function_enter`: The location points to the right parenthesis after the function arguments at + * the call site and the requirement says that the called function is entered. The key constraint + * has to be omitted in this case. + * - `function_return`: Such a requirement says that a given function call has been evaluated and + * the returned value satisfies a given constraint. The location points to the right parenthesis + * after the function arguments at the call site. The constraint is a mapping with keys format and + * value. We currently support only ACSL expressions of the form `\result + * `, where `` is one of `==`, `!=`, `<=`, `<`, `>`, `>=` and + * `` is a constant expression. The value of format has to be `acsl_expression`. + * - `branching`: A requirement of this type says that a given branching is evaluated in a given + * way. The location points to a branching keyword like `if`, `while`, `switch`, or to the + * character `?` in the ternary operator (`?:`). The constraint is then a mapping with only one + * key value. For binary branchings, value can be either `true` or `false` saying whether the true + * branch is used or not. For the keyword switch, value holds an integer constant or default. The + * integer constant specifies the value of the controlling expression of the switch statement. The + * value default says that the value of this expression does not match any case of the switch with + * the potential exception of the default case. * - * - `assumption`: - * The location has to point to the beginning of a statement or a declaration inside a compound statement. - * A requirement of this type says that a given constraint is satisfied before the pointed statement - * or declaration inside a compound statement. - * The constraint is a mapping with two keys: `format` specifies the language of the assumption and - * `value` contains a side-effect-free assumption over variables in the current scope. - * The value of `format` is `c_expression` as C expressions are the only assumptions currently supported. - * In future, we plan to support also assumptions in ACSL. - * - `target`: - * This type of requirement can be used only with action `follow` and it marks the program location where the property is violated. - * More precisely, the location points at the first character of the statement or - * full expression whose evaluation is sequenced directly before the violation occurs, - * i.e., there is no other evaluation sequenced before the violation and the sequence point associated with the location. - * This also implies that it can only point to a function call if it calls a function of the C standard library - * that violates the property or if the function call itself is the property violation. - * The key constraint has to be omitted for type `target`. - * - `function_enter`: - * The location points to the right parenthesis after the function arguments at the call site and the requirement - * says that the called function is entered. The key constraint has to be omitted in this case. - * - `function_return`: - * Such a requirement says that a given function call has been evaluated and the returned - * value satisfies a given constraint. The location points to the right parenthesis after the - * function arguments at the call site. The constraint is a mapping with keys format and value. - * We currently support only ACSL expressions of the form `\result `, - * where `` is one of `==`, `!=`, `<=`, `<`, `>`, `>=` and `` is a constant expression. - * The value of format has to be `acsl_expression`. - * - `branching`: - * A requirement of this type says that a given branching is evaluated in a given way. - * The location points to a branching keyword like `if`, `while`, `switch`, or to the character `?` - * in the ternary operator (`?:`). The constraint is then a mapping with only one key value. - * For binary branchings, value can be either `true` or `false` saying whether the true branch - * is used or not. For the keyword switch, value holds an integer constant or default. The - * integer constant specifies the value of the controlling expression of the switch statement. - * The value default says that the value of this expression does not match any case of the - * switch with the potential exception of the default case. - * - * An `assumption` waypoint is evaluated at the sequence point - * immediately before the waypoint location. The waypoint is passed if - * the given constraint evaluates to true. A `branching` waypoint - * is evaluated at the sequence point immediately after evaluation of the - * controlling expression of the corresponding branching statement. The - * waypoint is passed if the resulting value of the controlling - * expression corresponds to the given constraint. A - * `function_enter` waypoint is evaluated at the sequence point - * immediately after evaluation of all arguments of the function - * call. The waypoint is passed without any additional constraint. A - * `function_return` waypoint is evaluated immediately after - * evaluation of the corresponding function call. The waypoint is passed - * if the returned value satisfies the given constraint. + * An `assumption` waypoint is evaluated at the sequence point immediately before the waypoint + * location. The waypoint is passed if the given constraint evaluates to true. A `branching` + * waypoint is evaluated at the sequence point immediately after evaluation of the controlling + * expression of the corresponding branching statement. The waypoint is passed if the resulting + * value of the controlling expression corresponds to the given constraint. A `function_enter` + * waypoint is evaluated at the sequence point immediately after evaluation of all arguments of the + * function call. The waypoint is passed without any additional constraint. A `function_return` + * waypoint is evaluated immediately after evaluation of the corresponding function call. The + * waypoint is passed if the returned value satisfies the given constraint. * * @param type - * @param constraint The constraint of the waypoint. A constraint is not allowed for type `target`. - * @param location The `location` is a mapping with mandatory keys file_name and line. All other keys are optional. If the location provides an inconsistent information (e.g., identifier specifies a function that is not called at the given column on the given line ), the witness is syntactically invalid. - * @param action Action `follow` means that the waypoint should be passed through. Action `avoid` means that the waypoint should be avoided. + * @param constraint The constraint of the waypoint. A constraint is not allowed for type `target`. + * @param location The `location` is a mapping with mandatory keys file_name and line. All other + * keys are optional. If the location provides an inconsistent information (e.g., identifier + * specifies a function that is not called at the given column on the given line ), the witness is + * syntactically invalid. + * @param action Action `follow` means that the waypoint should be passed through. Action `avoid` + * means that the waypoint should be avoided. */ - -@Serializable data class Waypoint( - val type: WaypointType, - val constraint: Constraint? = null, - val location: Location, - val action: Action, +@Serializable +data class Waypoint( + val type: WaypointType, + val constraint: Constraint? = null, + val location: Location, + val action: Action, ) -@Serializable enum class WaypointType { - @SerialName("assumption") ASSUMPTION, - @SerialName("target") TARGET, - @SerialName("function_enter") FUNCTION_ENTER, - @SerialName("function_return") FUNCTION_RETURN, - @SerialName("branching") BRANCHING, +@Serializable +enum class WaypointType { + @SerialName("assumption") ASSUMPTION, + @SerialName("target") TARGET, + @SerialName("function_enter") FUNCTION_ENTER, + @SerialName("function_return") FUNCTION_RETURN, + @SerialName("branching") BRANCHING, } /** * The constraint of the waypoint. A constraint is not allowed for type `target`. + * * @param value * @param format */ -@Serializable data class Constraint( - val value: String, - val format: Format? = null, -) +@Serializable data class Constraint(val value: String, val format: Format? = null) -@Serializable enum class Format { - @SerialName("c_expression") C_EXPRESSION, - @SerialName("acsl_expression") ACSL_EXPRESSION, +@Serializable +enum class Format { + @SerialName("c_expression") C_EXPRESSION, + @SerialName("acsl_expression") ACSL_EXPRESSION, } /** - * The `location` is a mapping with mandatory keys file_name and line. All other keys are optional. If the location provides an inconsistent information (e.g., identifier specifies a function that is not called at the given column on the given line ), the witness is syntactically invalid. - * @param fileName The name of the file of the location + * The `location` is a mapping with mandatory keys file_name and line. All other keys are optional. + * If the location provides an inconsistent information (e.g., identifier specifies a function that + * is not called at the given column on the given line ), the witness is syntactically invalid. + * + * @param fileName The name of the file of the location * @param line The line number pf the program location in the file. - * @param column The key `column` specifies the column number of the location, i.e., the position of the `column`-th character in the line that the location points to (value 1 is the position of the first character). If the column is not given, then it is interpreted as the leftmost suitable position on the line, where suitability is given by `type`. - * @param function The key `function` gives the name of the function containing the location. It is usually determined by the `file_name` and `line`, but the information can improve human readability of the witness. + * @param column The key `column` specifies the column number of the location, i.e., the position of + * the `column`-th character in the line that the location points to (value 1 is the position of + * the first character). If the column is not given, then it is interpreted as the leftmost + * suitable position on the line, where suitability is given by `type`. + * @param function The key `function` gives the name of the function containing the location. It is + * usually determined by the `file_name` and `line`, but the information can improve human + * readability of the witness. */ -@Serializable data class Location( - @SerialName("file_name") - val fileName: String, - val line: Int, - val column: Int? = null, - val function: String? = null, +@Serializable +data class Location( + @SerialName("file_name") val fileName: String, + val line: Int, + val column: Int? = null, + val function: String? = null, ) /** - * Action `follow` means that the waypoint should be passed through. - * Action `avoid` means that the waypoint should be avoided. + * Action `follow` means that the waypoint should be passed through. Action `avoid` means that the + * waypoint should be avoided. */ -@Serializable enum class Action { - @SerialName("follow") FOLLOW, - @SerialName("avoid") AVOID, +@Serializable +enum class Action { + @SerialName("follow") FOLLOW, + @SerialName("avoid") AVOID, } -@Serializable data class Invariant( - val type: InvariantType, - val location: Location, - val value: String, - val format: Format, +@Serializable +data class Invariant( + val type: InvariantType, + val location: Location, + val value: String, + val format: Format, ) -@Serializable enum class InvariantType { - @SerialName("loop_invariant") LOOP_INVARIANT, - @SerialName("location_invariant") LOCATION_INVARIANT, -} \ No newline at end of file +@Serializable +enum class InvariantType { + @SerialName("loop_invariant") LOOP_INVARIANT, + @SerialName("location_invariant") LOCATION_INVARIANT, +} diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt index 8e0c2b4d39..75d179405f 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliParseTest.kt @@ -18,262 +18,303 @@ package hu.bme.mit.theta.xcfa.cli import com.google.common.base.Preconditions.checkState import hu.bme.mit.theta.frontend.chc.ChcFrontend import hu.bme.mit.theta.xcfa.cli.XcfaCli.Companion.main +import java.util.stream.Stream +import kotlin.io.path.createTempDirectory import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource -import java.io.File -import java.util.stream.Stream -import kotlin.io.path.createTempDirectory class XcfaCliParseTest { - companion object { + companion object { - @JvmStatic - fun cFiles(): Stream { - return Stream.of( - Arguments.of("/c/dekker.i"), - Arguments.of("/c/litmustest/singlethread/00assignment.c"), - Arguments.of("/c/litmustest/singlethread/01cast.c"), - Arguments.of("/c/litmustest/singlethread/02types.c"), - Arguments.of("/c/litmustest/singlethread/03bitwise.c"), - Arguments.of("/c/litmustest/singlethread/04real.c"), - Arguments.of("/c/litmustest/singlethread/05math.c"), - Arguments.of("/c/litmustest/singlethread/06arrays.c"), - Arguments.of("/c/litmustest/singlethread/07arrayinit.c"), - Arguments.of("/c/litmustest/singlethread/08vararray.c"), -// Arguments.of("/c/litmustest/singlethread/09struct.c"), -// Arguments.of("/c/litmustest/singlethread/10ptr.c"), -// Arguments.of("/c/litmustest/singlethread/11ptrs.c"), -// Arguments.of("/c/litmustest/singlethread/12ptrtypes.c"), - Arguments.of("/c/litmustest/singlethread/13typedef.c"), - Arguments.of("/c/litmustest/singlethread/14ushort.c"), - Arguments.of("/c/litmustest/singlethread/15addition.c"), - Arguments.of("/c/litmustest/singlethread/16loop.c"), - Arguments.of("/c/litmustest/singlethread/17recursive.c"), - Arguments.of("/c/litmustest/singlethread/18multithread.c"), - Arguments.of("/c/litmustest/singlethread/19dportest.c"), - Arguments.of("/c/litmustest/singlethread/20testinline.c"), - Arguments.of("/c/litmustest/singlethread/21namecollision.c"), - Arguments.of("/c/litmustest/singlethread/22nondet.c"), - Arguments.of("/c/litmustest/singlethread/23overflow.c"), - Arguments.of("/c/litmustest/singlethread/25malloc.c"), - ) - } - - @JvmStatic - fun simpleCFiles(): Stream { - return Stream.of( - Arguments.of("/c/litmustest/singlethread/00assignment.c"), - Arguments.of("/c/litmustest/singlethread/01cast.c"), - Arguments.of("/c/litmustest/singlethread/02types.c"), - Arguments.of("/c/litmustest/singlethread/03bitwise.c"), - Arguments.of("/c/litmustest/singlethread/14ushort.c"), - Arguments.of("/c/litmustest/singlethread/15addition.c"), - Arguments.of("/c/litmustest/singlethread/16loop.c"), - Arguments.of("/c/litmustest/singlethread/17recursive.c"), - Arguments.of("/c/litmustest/singlethread/21namecollision.c"), - Arguments.of("/c/litmustest/singlethread/22nondet.c"), - Arguments.of("/c/litmustest/singlethread/23overflow.c"), - ) - } + @JvmStatic + fun cFiles(): Stream { + return Stream.of( + Arguments.of("/c/dekker.i"), + Arguments.of("/c/litmustest/singlethread/00assignment.c"), + Arguments.of("/c/litmustest/singlethread/01cast.c"), + Arguments.of("/c/litmustest/singlethread/02types.c"), + Arguments.of("/c/litmustest/singlethread/03bitwise.c"), + Arguments.of("/c/litmustest/singlethread/04real.c"), + Arguments.of("/c/litmustest/singlethread/05math.c"), + Arguments.of("/c/litmustest/singlethread/06arrays.c"), + Arguments.of("/c/litmustest/singlethread/07arrayinit.c"), + Arguments.of("/c/litmustest/singlethread/08vararray.c"), + // Arguments.of("/c/litmustest/singlethread/09struct.c"), + // Arguments.of("/c/litmustest/singlethread/10ptr.c"), + // Arguments.of("/c/litmustest/singlethread/11ptrs.c"), + // Arguments.of("/c/litmustest/singlethread/12ptrtypes.c"), + Arguments.of("/c/litmustest/singlethread/13typedef.c"), + Arguments.of("/c/litmustest/singlethread/14ushort.c"), + Arguments.of("/c/litmustest/singlethread/15addition.c"), + Arguments.of("/c/litmustest/singlethread/16loop.c"), + Arguments.of("/c/litmustest/singlethread/17recursive.c"), + Arguments.of("/c/litmustest/singlethread/18multithread.c"), + Arguments.of("/c/litmustest/singlethread/19dportest.c"), + Arguments.of("/c/litmustest/singlethread/20testinline.c"), + Arguments.of("/c/litmustest/singlethread/21namecollision.c"), + Arguments.of("/c/litmustest/singlethread/22nondet.c"), + Arguments.of("/c/litmustest/singlethread/23overflow.c"), + Arguments.of("/c/litmustest/singlethread/25malloc.c"), + ) + } - @JvmStatic - fun llvmFiles(): Stream { - return Stream.of( - Arguments.of("/c/dekker.i"), - Arguments.of("/c/litmustest/singlethread/00assignment.c"), -// Arguments.of("/c/litmustest/singlethread/01cast.c"), - Arguments.of("/c/litmustest/singlethread/02types.c"), - Arguments.of("/c/litmustest/singlethread/03bitwise.c"), -// Arguments.of("/c/litmustest/singlethread/04real.c"), -// Arguments.of("/c/litmustest/singlethread/05math.c"), - Arguments.of("/c/litmustest/singlethread/06arrays.c"), - Arguments.of("/c/litmustest/singlethread/07arrayinit.c"), - Arguments.of("/c/litmustest/singlethread/08vararray.c"), -// Arguments.of("/c/litmustest/singlethread/09struct.c"), -// Arguments.of("/c/litmustest/singlethread/10ptr.c"), -// Arguments.of("/c/litmustest/singlethread/11ptrs.c"), -// Arguments.of("/c/litmustest/singlethread/12ptrtypes.c"), - Arguments.of("/c/litmustest/singlethread/13typedef.c"), - Arguments.of("/c/litmustest/singlethread/14ushort.c"), - Arguments.of("/c/litmustest/singlethread/15addition.c"), - Arguments.of("/c/litmustest/singlethread/16loop.c"), -// Arguments.of("/c/litmustest/singlethread/17recursive.c"), - Arguments.of("/c/litmustest/singlethread/18multithread.c"), - Arguments.of("/c/litmustest/singlethread/19dportest.c"), - Arguments.of("/c/litmustest/singlethread/20testinline.c"), - Arguments.of("/c/litmustest/singlethread/21namecollision.c"), -// Arguments.of("/c/litmustest/singlethread/22nondet.c"), - Arguments.of("/c/litmustest/singlethread/23overflow.c"), - ) - } + @JvmStatic + fun simpleCFiles(): Stream { + return Stream.of( + Arguments.of("/c/litmustest/singlethread/00assignment.c"), + Arguments.of("/c/litmustest/singlethread/01cast.c"), + Arguments.of("/c/litmustest/singlethread/02types.c"), + Arguments.of("/c/litmustest/singlethread/03bitwise.c"), + Arguments.of("/c/litmustest/singlethread/14ushort.c"), + Arguments.of("/c/litmustest/singlethread/15addition.c"), + Arguments.of("/c/litmustest/singlethread/16loop.c"), + Arguments.of("/c/litmustest/singlethread/17recursive.c"), + Arguments.of("/c/litmustest/singlethread/21namecollision.c"), + Arguments.of("/c/litmustest/singlethread/22nondet.c"), + Arguments.of("/c/litmustest/singlethread/23overflow.c"), + ) + } - @JvmStatic - fun chcFiles(): Stream { - return Stream.of( - Arguments.of("/chc/chc-LIA-Arrays_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), - Arguments.of("/chc/chc-LIA-Lin-Arrays_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), - Arguments.of("/chc/chc-LIA-Lin_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), - Arguments.of("/chc/chc-LIA_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), + @JvmStatic + fun llvmFiles(): Stream { + return Stream.of( + Arguments.of("/c/dekker.i"), + Arguments.of("/c/litmustest/singlethread/00assignment.c"), + // Arguments.of("/c/litmustest/singlethread/01cast.c"), + Arguments.of("/c/litmustest/singlethread/02types.c"), + Arguments.of("/c/litmustest/singlethread/03bitwise.c"), + // Arguments.of("/c/litmustest/singlethread/04real.c"), + // Arguments.of("/c/litmustest/singlethread/05math.c"), + Arguments.of("/c/litmustest/singlethread/06arrays.c"), + Arguments.of("/c/litmustest/singlethread/07arrayinit.c"), + Arguments.of("/c/litmustest/singlethread/08vararray.c"), + // Arguments.of("/c/litmustest/singlethread/09struct.c"), + // Arguments.of("/c/litmustest/singlethread/10ptr.c"), + // Arguments.of("/c/litmustest/singlethread/11ptrs.c"), + // Arguments.of("/c/litmustest/singlethread/12ptrtypes.c"), + Arguments.of("/c/litmustest/singlethread/13typedef.c"), + Arguments.of("/c/litmustest/singlethread/14ushort.c"), + Arguments.of("/c/litmustest/singlethread/15addition.c"), + Arguments.of("/c/litmustest/singlethread/16loop.c"), + // Arguments.of("/c/litmustest/singlethread/17recursive.c"), + Arguments.of("/c/litmustest/singlethread/18multithread.c"), + Arguments.of("/c/litmustest/singlethread/19dportest.c"), + Arguments.of("/c/litmustest/singlethread/20testinline.c"), + Arguments.of("/c/litmustest/singlethread/21namecollision.c"), + // Arguments.of("/c/litmustest/singlethread/22nondet.c"), + Arguments.of("/c/litmustest/singlethread/23overflow.c"), + ) + } -// Arguments.of("/chc/chc-LIA-Arrays_000.smt2", ChcFrontend.ChcTransformation.FORWARD), // nonlin - Arguments.of("/chc/chc-LIA-Lin-Arrays_000.smt2", ChcFrontend.ChcTransformation.FORWARD), - Arguments.of("/chc/chc-LIA-Lin_000.smt2", ChcFrontend.ChcTransformation.FORWARD), -// Arguments.of("/chc/chc-LIA_000.smt2", ChcFrontend.ChcTransformation.FORWARD), // nonlin + @JvmStatic + fun chcFiles(): Stream { + return Stream.of( + Arguments.of("/chc/chc-LIA-Arrays_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), + Arguments.of("/chc/chc-LIA-Lin-Arrays_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), + Arguments.of("/chc/chc-LIA-Lin_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), + Arguments.of("/chc/chc-LIA_000.smt2", ChcFrontend.ChcTransformation.PORTFOLIO), - Arguments.of("/chc/chc-LIA-Arrays_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), - Arguments.of("/chc/chc-LIA-Lin-Arrays_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), - Arguments.of("/chc/chc-LIA-Lin_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), - Arguments.of("/chc/chc-LIA_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), - ) - } + // Arguments.of("/chc/chc-LIA-Arrays_000.smt2", + // ChcFrontend.ChcTransformation.FORWARD), // nonlin + Arguments.of("/chc/chc-LIA-Lin-Arrays_000.smt2", ChcFrontend.ChcTransformation.FORWARD), + Arguments.of("/chc/chc-LIA-Lin_000.smt2", ChcFrontend.ChcTransformation.FORWARD), + // Arguments.of("/chc/chc-LIA_000.smt2", + // ChcFrontend.ChcTransformation.FORWARD), // nonlin - @JvmStatic - fun dslFiles(): Stream { - return Stream.of( - Arguments.of("/dsl/async.xcfa.kts"), - Arguments.of("/dsl/sync.xcfa.kts"), - ) - } + Arguments.of("/chc/chc-LIA-Arrays_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), + Arguments.of("/chc/chc-LIA-Lin-Arrays_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), + Arguments.of("/chc/chc-LIA-Lin_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), + Arguments.of("/chc/chc-LIA_000.smt2", ChcFrontend.ChcTransformation.BACKWARD), + ) + } - @JvmStatic - fun jsonFiles(): Stream { - return Stream.of( - Arguments.of("/json/00assignment.c.json"), - Arguments.of("/json/01cast.c.json"), - Arguments.of("/json/02types.c.json"), - Arguments.of("/json/03bitwise.c.json"), - Arguments.of("/json/04real.c.json"), - Arguments.of("/json/05math.c.json"), - Arguments.of("/json/06arrays.c.json"), - Arguments.of("/json/07arrayinit.c.json"), - Arguments.of("/json/08vararray.c.json"), -// Arguments.of("/json/09struct.c.json"), -// Arguments.of("/json/10ptr.c.json"), -// Arguments.of("/json/11ptrs.c.json"), -// Arguments.of("/json/12ptrtypes.c.json"), - Arguments.of("/json/13typedef.c.json"), - Arguments.of("/json/14ushort.c.json"), - Arguments.of("/json/15addition.c.json"), - Arguments.of("/json/16loop.c.json"), - Arguments.of("/json/17recursive.c.json"), - Arguments.of("/json/18multithread.c.json"), - Arguments.of("/json/19dportest.c.json"), - Arguments.of("/json/20testinline.c.json"), - Arguments.of("/json/21namecollision.c.json"), - Arguments.of("/json/22nondet.c.json"), - Arguments.of("/json/23overflow.c.json"), - ) - } + @JvmStatic + fun dslFiles(): Stream { + return Stream.of(Arguments.of("/dsl/async.xcfa.kts"), Arguments.of("/dsl/sync.xcfa.kts")) } - @ParameterizedTest - @MethodSource("cFiles") - fun testCParse(filePath: String) { - main(arrayOf( - "--input-type", "C", - "--input", javaClass.getResource(filePath)!!.path, - "--backend", "NONE", "--stacktrace", - "--debug" - )) + @JvmStatic + fun jsonFiles(): Stream { + return Stream.of( + Arguments.of("/json/00assignment.c.json"), + Arguments.of("/json/01cast.c.json"), + Arguments.of("/json/02types.c.json"), + Arguments.of("/json/03bitwise.c.json"), + Arguments.of("/json/04real.c.json"), + Arguments.of("/json/05math.c.json"), + Arguments.of("/json/06arrays.c.json"), + Arguments.of("/json/07arrayinit.c.json"), + Arguments.of("/json/08vararray.c.json"), + // Arguments.of("/json/09struct.c.json"), + // Arguments.of("/json/10ptr.c.json"), + // Arguments.of("/json/11ptrs.c.json"), + // Arguments.of("/json/12ptrtypes.c.json"), + Arguments.of("/json/13typedef.c.json"), + Arguments.of("/json/14ushort.c.json"), + Arguments.of("/json/15addition.c.json"), + Arguments.of("/json/16loop.c.json"), + Arguments.of("/json/17recursive.c.json"), + Arguments.of("/json/18multithread.c.json"), + Arguments.of("/json/19dportest.c.json"), + Arguments.of("/json/20testinline.c.json"), + Arguments.of("/json/21namecollision.c.json"), + Arguments.of("/json/22nondet.c.json"), + Arguments.of("/json/23overflow.c.json"), + ) } + } -// @ParameterizedTest -// @MethodSource("llvmFiles") -// fun testLLVMParse(filePath: String) { -// if (OsHelper.getOs() == OsHelper.OperatingSystem.LINUX) { -// main(arrayOf( -// "--input-type", "LLVM", -// "--input", javaClass.getResource(filePath)!!.path, -// "--backend", "NONE", "--stacktrace" -// )) -// } -// } + @ParameterizedTest + @MethodSource("cFiles") + fun testCParse(filePath: String) { + main( + arrayOf( + "--input-type", + "C", + "--input", + javaClass.getResource(filePath)!!.path, + "--backend", + "NONE", + "--stacktrace", + "--debug", + ) + ) + } - @ParameterizedTest - @MethodSource("chcFiles") - fun testCHCParse(filePath: String, chcTransformation: ChcFrontend.ChcTransformation) { - main(arrayOf( - "--input-type", "CHC", - "--chc-transformation", chcTransformation.toString(), - "--input", javaClass.getResource(filePath)!!.path, - "--backend", "NONE", - "--stacktrace", - "--debug" - )) - } + // @ParameterizedTest + // @MethodSource("llvmFiles") + // fun testLLVMParse(filePath: String) { + // if (OsHelper.getOs() == OsHelper.OperatingSystem.LINUX) { + // main(arrayOf( + // "--input-type", "LLVM", + // "--input", javaClass.getResource(filePath)!!.path, + // "--backend", "NONE", "--stacktrace" + // )) + // } + // } - @ParameterizedTest - @MethodSource("dslFiles") - fun testDSLParse(filePath: String) { - main(arrayOf( - "--input-type", "DSL", - "--input", javaClass.getResource(filePath)!!.path, - "--backend", "NONE", - "--stacktrace", - "--debug" - )) - } + @ParameterizedTest + @MethodSource("chcFiles") + fun testCHCParse(filePath: String, chcTransformation: ChcFrontend.ChcTransformation) { + main( + arrayOf( + "--input-type", + "CHC", + "--chc-transformation", + chcTransformation.toString(), + "--input", + javaClass.getResource(filePath)!!.path, + "--backend", + "NONE", + "--stacktrace", + "--debug", + ) + ) + } - @ParameterizedTest - @MethodSource("jsonFiles") - fun testJSONParse(filePath: String) { - main(arrayOf( - "--input-type", "JSON", - "--input", javaClass.getResource(filePath)!!.path, - "--backend", "NONE", - "--stacktrace", - "--debug" - )) - } + @ParameterizedTest + @MethodSource("dslFiles") + fun testDSLParse(filePath: String) { + main( + arrayOf( + "--input-type", + "DSL", + "--input", + javaClass.getResource(filePath)!!.path, + "--backend", + "NONE", + "--stacktrace", + "--debug", + ) + ) + } - @ParameterizedTest - @MethodSource("cFiles") - fun testJSONParseRoundTrip(filePath: String) { - val temp = createTempDirectory() - main(arrayOf( - "--enable-output", - "--input-type", "C", - "--input", javaClass.getResource(filePath)!!.path, - "--backend", "NONE", - "--stacktrace", - "--output-directory", temp.toAbsolutePath().toString(), - "--debug" - )) - val xcfaJson = temp.resolve("xcfa.json").toFile() - main(arrayOf( - "--input-type", "JSON", - "--input", xcfaJson.absolutePath.toString(), - "--backend", "NONE", - "--stacktrace", - "--debug" - )) - temp.toFile().deleteRecursively() - } + @ParameterizedTest + @MethodSource("jsonFiles") + fun testJSONParse(filePath: String) { + main( + arrayOf( + "--input-type", + "JSON", + "--input", + javaClass.getResource(filePath)!!.path, + "--backend", + "NONE", + "--stacktrace", + "--debug", + ) + ) + } - @ParameterizedTest - @MethodSource("simpleCFiles") - fun testCParseRoundTrip(filePath: String) { - val temp = createTempDirectory() - main(arrayOf( - "--enable-output", - "--input-type", "C", - "--input", javaClass.getResource(filePath)!!.path, - "--backend", "NONE", - "--stacktrace", - "--output-directory", temp.toAbsolutePath().toString(), - "--debug" - )) - val xcfaC = temp.resolve("xcfa.c").toFile() - checkState(xcfaC.exists(), "File does not exist: $xcfaC") - main(arrayOf( - "--input-type", "C", - "--input", xcfaC.absolutePath.toString(), - "--backend", "NONE", - "--stacktrace", - "--debug" - )) - temp.toFile().deleteRecursively() - } + @ParameterizedTest + @MethodSource("cFiles") + fun testJSONParseRoundTrip(filePath: String) { + val temp = createTempDirectory() + main( + arrayOf( + "--enable-output", + "--input-type", + "C", + "--input", + javaClass.getResource(filePath)!!.path, + "--backend", + "NONE", + "--stacktrace", + "--output-directory", + temp.toAbsolutePath().toString(), + "--debug", + ) + ) + val xcfaJson = temp.resolve("xcfa.json").toFile() + main( + arrayOf( + "--input-type", + "JSON", + "--input", + xcfaJson.absolutePath.toString(), + "--backend", + "NONE", + "--stacktrace", + "--debug", + ) + ) + temp.toFile().deleteRecursively() + } + @ParameterizedTest + @MethodSource("simpleCFiles") + fun testCParseRoundTrip(filePath: String) { + val temp = createTempDirectory() + main( + arrayOf( + "--enable-output", + "--input-type", + "C", + "--input", + javaClass.getResource(filePath)!!.path, + "--backend", + "NONE", + "--stacktrace", + "--output-directory", + temp.toAbsolutePath().toString(), + "--debug", + ) + ) + val xcfaC = temp.resolve("xcfa.c").toFile() + checkState(xcfaC.exists(), "File does not exist: $xcfaC") + main( + arrayOf( + "--input-type", + "C", + "--input", + xcfaC.absolutePath.toString(), + "--backend", + "NONE", + "--stacktrace", + "--debug", + ) + ) + temp.toFile().deleteRecursively() + } } diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt index 5ae3925c3e..bc39de1553 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt @@ -16,14 +16,14 @@ package hu.bme.mit.theta.xcfa.cli import hu.bme.mit.theta.xcfa.cli.XcfaCli.Companion.main -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.MethodSource import java.util.stream.Stream import kotlin.io.path.absolutePathString import kotlin.io.path.createTempDirectory import kotlin.io.path.exists +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource data class WitnessEdge( val startlineRange: Pair?, diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt index f157011728..6744a352b0 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/YamlParseTest.kt @@ -13,60 +13,56 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.cli import com.charleskorn.kaml.Yaml import hu.bme.mit.theta.xcfa.cli.witnesses.* +import java.util.* import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import java.util.* class YamlParseTest { - @Test - fun serialize() { - val witness = YamlWitness( - entryType = EntryType.VIOLATION, - metadata = Metadata( - formatVersion = "2.0", - uuid = UUID.randomUUID().toString(), - creationTime = getIsoDate(), - producer = Producer( - name = "test", - version = "1.0.0", - ), - task = Task( - inputFiles = listOf("example.c"), - inputFileHashes = listOf("hash"), - specification = "unreach_call", - dataModel = DataModel.LP64, - language = Language.C, + @Test + fun serialize() { + val witness = + YamlWitness( + entryType = EntryType.VIOLATION, + metadata = + Metadata( + formatVersion = "2.0", + uuid = UUID.randomUUID().toString(), + creationTime = getIsoDate(), + producer = Producer(name = "test", version = "1.0.0"), + task = + Task( + inputFiles = listOf("example.c"), + inputFileHashes = listOf("hash"), + specification = "unreach_call", + dataModel = DataModel.LP64, + language = Language.C, + ), + ), + content = + listOf( + ContentItem( + Segment( + Waypoint( + type = WaypointType.ASSUMPTION, + constraint = Constraint(value = "1 < x", format = Format.C_EXPRESSION), + location = Location(fileName = "example.c", line = 15), + action = Action.FOLLOW, ) - ), - content = listOf( - ContentItem( - Segment(Waypoint( - type = WaypointType.ASSUMPTION, - constraint = Constraint( - value = "1 < x", - format = Format.C_EXPRESSION, - ), - location = Location( - fileName = "example.c", - line = 15, - ), - action = Action.FOLLOW, - )) - ), - ), - ) + ) + ) + ), + ) - val result = WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness) + val result = WitnessYamlConfig.encodeToString(YamlWitness.serializer(), witness) - System.err.println(result) + System.err.println(result) - val parsedPack = Yaml.default.decodeFromString(YamlWitness.serializer(), result) + val parsedPack = Yaml.default.decodeFromString(YamlWitness.serializer(), result) - Assertions.assertEquals(witness, parsedPack) - } -} \ No newline at end of file + Assertions.assertEquals(witness, parsedPack) + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt index f4a5801ad3..4c7c6673ef 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaAdapter.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.gson import com.google.gson.Gson @@ -29,183 +28,199 @@ import java.util.* class XcfaAdapter(val gsonSupplier: () -> Gson) : TypeAdapter() { - private lateinit var gson: Gson - override fun write(writer: JsonWriter, value: XCFA) { - initGson() - writer.beginObject() - writer.name("name").value(value.name) - //vars - writer.name("vars") - gson.toJson(gson.toJsonTree(value.vars), writer) - - //procedures - writer.name("procedures").beginArray() - for (xcfaProcedure in value.procedures) { - writer.beginObject() - writer.name("name").value(xcfaProcedure.name) - writer.name("params") - gson.toJson(gson.toJsonTree(xcfaProcedure.params), writer) - writer.name("vars") - gson.toJson(gson.toJsonTree(xcfaProcedure.vars), writer) - writer.name("locs") - gson.toJson(gson.toJsonTree(xcfaProcedure.locs), writer) - writer.name("edges") - writer.beginArray().also { - xcfaProcedure.edges.forEach { - writer.beginObject() - .name("source").value(it.source.name) - .name("target").value(it.target.name) - .name("label") - gson.toJson(gson.toJsonTree(it.label), writer) - writer.name("metadata") - gson.toJson(gson.toJsonTree(it.metadata), writer) - writer.endObject() - } - }.endArray() - - writer.endObject() - } - writer.endArray() - - //initProcedures - writer.name("initProcedures").beginArray() - value.initProcedures.forEach { - writer.beginObject() - writer.name("params") - gson.toJson(gson.toJsonTree(it.second), writer) - writer.name("procedure").value(it.first.name) + private lateinit var gson: Gson + + override fun write(writer: JsonWriter, value: XCFA) { + initGson() + writer.beginObject() + writer.name("name").value(value.name) + // vars + writer.name("vars") + gson.toJson(gson.toJsonTree(value.vars), writer) + + // procedures + writer.name("procedures").beginArray() + for (xcfaProcedure in value.procedures) { + writer.beginObject() + writer.name("name").value(xcfaProcedure.name) + writer.name("params") + gson.toJson(gson.toJsonTree(xcfaProcedure.params), writer) + writer.name("vars") + gson.toJson(gson.toJsonTree(xcfaProcedure.vars), writer) + writer.name("locs") + gson.toJson(gson.toJsonTree(xcfaProcedure.locs), writer) + writer.name("edges") + writer + .beginArray() + .also { + xcfaProcedure.edges.forEach { + writer + .beginObject() + .name("source") + .value(it.source.name) + .name("target") + .value(it.target.name) + .name("label") + gson.toJson(gson.toJsonTree(it.label), writer) + writer.name("metadata") + gson.toJson(gson.toJsonTree(it.metadata), writer) writer.endObject() + } } - writer.endArray() + .endArray() - writer.endObject() + writer.endObject() } - - override fun read(reader: JsonReader): XCFA { - initGson() - - reader.beginObject() - lateinit var name: String - lateinit var vars: Set - lateinit var xcfaProcedures: Map - lateinit var initProcedures: List>>> - - val varsType = object : TypeToken>() {}.type - - lateinit var xcfa: XCFA - while (reader.peek() != JsonToken.END_OBJECT) { - val nextName = reader.nextName() - when (nextName) { - "name" -> name = reader.nextString() - "vars" -> vars = gson.fromJson(reader, varsType) - "procedures" -> { - xcfa = XCFA(name, vars) - xcfaProcedures = parseProcedures(reader, xcfa) - } - - "initProcedures" -> initProcedures = parseInitProcedures(reader, xcfaProcedures) - } + writer.endArray() + + // initProcedures + writer.name("initProcedures").beginArray() + value.initProcedures.forEach { + writer.beginObject() + writer.name("params") + gson.toJson(gson.toJsonTree(it.second), writer) + writer.name("procedure").value(it.first.name) + writer.endObject() + } + writer.endArray() + + writer.endObject() + } + + override fun read(reader: JsonReader): XCFA { + initGson() + + reader.beginObject() + lateinit var name: String + lateinit var vars: Set + lateinit var xcfaProcedures: Map + lateinit var initProcedures: List>>> + + val varsType = object : TypeToken>() {}.type + + lateinit var xcfa: XCFA + while (reader.peek() != JsonToken.END_OBJECT) { + val nextName = reader.nextName() + when (nextName) { + "name" -> name = reader.nextString() + "vars" -> vars = gson.fromJson(reader, varsType) + "procedures" -> { + xcfa = XCFA(name, vars) + xcfaProcedures = parseProcedures(reader, xcfa) } - reader.endObject() - return xcfa.recreate(xcfaProcedures.values.toSet(), initProcedures) + "initProcedures" -> initProcedures = parseInitProcedures(reader, xcfaProcedures) + } } - - private fun parseInitProcedures( - reader: JsonReader, - procedures: Map): List>>> { - reader.beginArray() - val ret = ArrayList>>>() - val paramsType = object : TypeToken>>() {}.type - while (reader.peek() != JsonToken.END_ARRAY) { - reader.beginObject() - lateinit var params: List> - lateinit var procedure: XcfaProcedure - while (reader.peek() != JsonToken.END_OBJECT) { - when (reader.nextName()) { - "params" -> params = gson.fromJson(reader, paramsType) - "procedure" -> procedure = checkNotNull(procedures[reader.nextString()]) - } - } - ret.add(Pair(procedure, params)) - reader.endObject() + reader.endObject() + + return xcfa.recreate(xcfaProcedures.values.toSet(), initProcedures) + } + + private fun parseInitProcedures( + reader: JsonReader, + procedures: Map, + ): List>>> { + reader.beginArray() + val ret = ArrayList>>>() + val paramsType = object : TypeToken>>() {}.type + while (reader.peek() != JsonToken.END_ARRAY) { + reader.beginObject() + lateinit var params: List> + lateinit var procedure: XcfaProcedure + while (reader.peek() != JsonToken.END_OBJECT) { + when (reader.nextName()) { + "params" -> params = gson.fromJson(reader, paramsType) + "procedure" -> procedure = checkNotNull(procedures[reader.nextString()]) } - reader.endArray() - return ret + } + ret.add(Pair(procedure, params)) + reader.endObject() } - - private fun parseProcedures(reader: JsonReader, xcfa: XCFA): Map { - reader.beginArray() - val ret = LinkedHashMap() - val paramsType = object : TypeToken, ParamDirection>>>() {}.type - val varsType = object : TypeToken>>() {}.type - val locsType = object : TypeToken>() {}.type - val labelType = object : TypeToken() {}.type - val metadataType = object : TypeToken() {}.type - - while (reader.peek() != JsonToken.END_ARRAY) { - reader.beginObject() - lateinit var name: String - lateinit var params: List, ParamDirection>> - lateinit var vars: Set> - lateinit var locs: Map - val edges: MutableSet = LinkedHashSet() - lateinit var initLoc: XcfaLocation - var finalLoc: XcfaLocation? = null - var errorLoc: XcfaLocation? = null - - while (reader.peek() != JsonToken.END_OBJECT) { + reader.endArray() + return ret + } + + private fun parseProcedures(reader: JsonReader, xcfa: XCFA): Map { + reader.beginArray() + val ret = LinkedHashMap() + val paramsType = object : TypeToken, ParamDirection>>>() {}.type + val varsType = object : TypeToken>>() {}.type + val locsType = object : TypeToken>() {}.type + val labelType = object : TypeToken() {}.type + val metadataType = object : TypeToken() {}.type + + while (reader.peek() != JsonToken.END_ARRAY) { + reader.beginObject() + lateinit var name: String + lateinit var params: List, ParamDirection>> + lateinit var vars: Set> + lateinit var locs: Map + val edges: MutableSet = LinkedHashSet() + lateinit var initLoc: XcfaLocation + var finalLoc: XcfaLocation? = null + var errorLoc: XcfaLocation? = null + + while (reader.peek() != JsonToken.END_OBJECT) { + when (reader.nextName()) { + "name" -> name = reader.nextString() + "params" -> params = gson.fromJson(reader, paramsType) + "vars" -> vars = gson.fromJson(reader, varsType) + "locs" -> { + val locations: Set = gson.fromJson(reader, locsType) + locations.forEach { + if (it.error) errorLoc = it + if (it.initial) initLoc = it + if (it.final) finalLoc = it + } + locs = locations.associateBy { it.name } + } + + "edges" -> { + reader.beginArray() + while (reader.peek() != JsonToken.END_ARRAY) { + reader.beginObject() + lateinit var source: XcfaLocation + lateinit var target: XcfaLocation + lateinit var label: XcfaLabel + lateinit var metadata: MetaData + while (reader.peek() != JsonToken.END_OBJECT) { when (reader.nextName()) { - "name" -> name = reader.nextString() - "params" -> params = gson.fromJson(reader, paramsType) - "vars" -> vars = gson.fromJson(reader, varsType) - "locs" -> { - val locations: Set = gson.fromJson(reader, locsType) - locations.forEach { - if (it.error) errorLoc = it - if (it.initial) initLoc = it - if (it.final) finalLoc = it - } - locs = locations.associateBy { it.name } - } - - "edges" -> { - reader.beginArray() - while (reader.peek() != JsonToken.END_ARRAY) { - reader.beginObject() - lateinit var source: XcfaLocation - lateinit var target: XcfaLocation - lateinit var label: XcfaLabel - lateinit var metadata: MetaData - while (reader.peek() != JsonToken.END_OBJECT) { - when (reader.nextName()) { - "source" -> source = checkNotNull(locs[reader.nextString()]) - "target" -> target = checkNotNull(locs[reader.nextString()]) - "label" -> label = gson.fromJson(reader, labelType) - "metadata" -> metadata = gson.fromJson(reader, metadataType) - } - } - val edge = XcfaEdge(source, target, label, metadata) - edges.add(edge) - source.outgoingEdges.add(edge) - target.incomingEdges.add(edge) - reader.endObject() - } - reader.endArray() - } + "source" -> source = checkNotNull(locs[reader.nextString()]) + "target" -> target = checkNotNull(locs[reader.nextString()]) + "label" -> label = gson.fromJson(reader, labelType) + "metadata" -> metadata = gson.fromJson(reader, metadataType) } + } + val edge = XcfaEdge(source, target, label, metadata) + edges.add(edge) + source.outgoingEdges.add(edge) + target.incomingEdges.add(edge) + reader.endObject() } - ret[name] = XcfaProcedure(name, params, vars, locs.values.toSet(), edges, initLoc, - Optional.ofNullable(finalLoc), - Optional.ofNullable(errorLoc)).also { it.parent = xcfa } - reader.endObject() + reader.endArray() + } } - reader.endArray() - return ret - } - - private fun initGson() { - if (!this::gson.isInitialized) gson = gsonSupplier() + } + ret[name] = + XcfaProcedure( + name, + params, + vars, + locs.values.toSet(), + edges, + initLoc, + Optional.ofNullable(finalLoc), + Optional.ofNullable(errorLoc), + ) + .also { it.parent = xcfa } + reader.endObject() } - -} \ No newline at end of file + reader.endArray() + return ret + } + + private fun initGson() { + if (!this::gson.isInitialized) gson = gsonSupplier() + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt index 02d6e50e50..0358151fce 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/gson/XcfaLocationAdapter.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.gson import com.google.gson.Gson @@ -26,47 +25,47 @@ import hu.bme.mit.theta.xcfa.model.XcfaLocation class XcfaLocationAdapter(val gsonSupplier: () -> Gson) : TypeAdapter() { - private lateinit var gson: Gson - override fun write(writer: JsonWriter, value: XcfaLocation) { - initGson() - writer.beginObject() - writer.name("name").value(value.name) - writer.name("initial").value(value.initial) - writer.name("final").value(value.final) - writer.name("error").value(value.error) - writer.name("metadata") - gson.toJson(gson.toJsonTree(value.metadata), writer) - writer.endObject() - } + private lateinit var gson: Gson - override fun read(reader: JsonReader): XcfaLocation { - initGson() - reader.beginObject() + override fun write(writer: JsonWriter, value: XcfaLocation) { + initGson() + writer.beginObject() + writer.name("name").value(value.name) + writer.name("initial").value(value.initial) + writer.name("final").value(value.final) + writer.name("error").value(value.error) + writer.name("metadata") + gson.toJson(gson.toJsonTree(value.metadata), writer) + writer.endObject() + } - lateinit var name: String - var initial = false - var final = false - var error = false - var metaData: MetaData? = null + override fun read(reader: JsonReader): XcfaLocation { + initGson() + reader.beginObject() - while (reader.hasNext()) { - val jsonName = reader.nextName() - when (jsonName) { - "name" -> name = reader.nextString() - "initial" -> initial = reader.nextBoolean() - "final" -> final = reader.nextBoolean() - "error" -> error = reader.nextBoolean() - "metaData" -> metaData = gson.fromJson(reader, MetaData::class.java) - else -> reader.skipValue() - } - } - reader.endObject() + lateinit var name: String + var initial = false + var final = false + var error = false + var metaData: MetaData? = null - return XcfaLocation(name, initial, final, error, metaData ?: EmptyMetaData) + while (reader.hasNext()) { + val jsonName = reader.nextName() + when (jsonName) { + "name" -> name = reader.nextString() + "initial" -> initial = reader.nextBoolean() + "final" -> final = reader.nextBoolean() + "error" -> error = reader.nextBoolean() + "metaData" -> metaData = gson.fromJson(reader, MetaData::class.java) + else -> reader.skipValue() + } } + reader.endObject() - private fun initGson() { - if (!this::gson.isInitialized) gson = gsonSupplier() - } + return XcfaLocation(name, initial, final, error, metaData ?: EmptyMetaData) + } -} \ No newline at end of file + private fun initGson() { + if (!this::gson.isInitialized) gson = gsonSupplier() + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt index 96b21e4b97..90e05c8a19 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/Dsl.kt @@ -30,287 +30,307 @@ import hu.bme.mit.theta.grammar.dsl.expr.ExpressionWrapper import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager fun xcfa(name: String, lambda: XcfaBuilder.() -> Unit): XCFA = - XcfaBuilder(name).apply(lambda).build() + XcfaBuilder(name).apply(lambda).build() class VarContext(val builder: XcfaBuilder, private val local: Boolean) { - infix fun String.type(type: Type): Pair = Pair(this, type) - - infix fun Pair.init(initValue: String): VarDecl { - val varDecl = Var(first, second) - builder.addVar( - XcfaGlobalVar(varDecl, - ExpressionWrapper(SimpleScope(SymbolTable()), initValue).instantiate( - Env()) as LitExpr<*>, - local)) - return varDecl - } + infix fun String.type(type: Type): Pair = Pair(this, type) + + infix fun Pair.init(initValue: String): VarDecl { + val varDecl = Var(first, second) + builder.addVar( + XcfaGlobalVar( + varDecl, + ExpressionWrapper(SimpleScope(SymbolTable()), initValue).instantiate(Env()) as LitExpr<*>, + local, + ) + ) + return varDecl + } } fun XcfaProcedureBuilder.lookup(name: String): VarDecl = - getVars().find { it.name.equals(name) } ?: parent.getVars().map { it.wrappedVar } - .find { it.name.equals(name) } ?: error("Variable $name not found in scope.") + getVars().find { it.name.equals(name) } + ?: parent.getVars().map { it.wrappedVar }.find { it.name.equals(name) } + ?: error("Variable $name not found in scope.") data class NamedSymbol(val _name: String) : Symbol { - override fun getName(): String { - return _name - } + override fun getName(): String { + return _name + } } fun XcfaProcedureBuilder.parse(expr: String): Expr { - val symbolTable = SymbolTable() - getVars().forEach { symbolTable.add(NamedSymbol(it.name)) } - parent.getVars().map { it.wrappedVar }.forEach { symbolTable.add(NamedSymbol(it.name)) } - val env = Env() - getVars().forEach { env.define(NamedSymbol(it.name), it) } - parent.getVars().map { it.wrappedVar }.forEach { env.define(NamedSymbol(it.name), it) } - - return ExpressionWrapper(SimpleScope(symbolTable), expr).instantiate(env) + val symbolTable = SymbolTable() + getVars().forEach { symbolTable.add(NamedSymbol(it.name)) } + parent.getVars().map { it.wrappedVar }.forEach { symbolTable.add(NamedSymbol(it.name)) } + val env = Env() + getVars().forEach { env.define(NamedSymbol(it.name), it) } + parent.getVars().map { it.wrappedVar }.forEach { env.define(NamedSymbol(it.name), it) } + + return ExpressionWrapper(SimpleScope(symbolTable), expr).instantiate(env) } @XcfaDsl class XcfaProcedureBuilderContext(val builder: XcfaProcedureBuilder) { - private val locationLut: MutableMap = LinkedHashMap() - val init: String = "init" - val err: String = "err" - val final: String = "final" - - init { - builder.createInitLoc() - builder.createErrorLoc() - builder.createFinalLoc() - locationLut[init] = builder.initLoc - locationLut[err] = builder.errorLoc.get() - locationLut[final] = builder.finalLoc.get() + private val locationLut: MutableMap = LinkedHashMap() + val init: String = "init" + val err: String = "err" + val final: String = "final" + + init { + builder.createInitLoc() + builder.createErrorLoc() + builder.createFinalLoc() + locationLut[init] = builder.initLoc + locationLut[err] = builder.errorLoc.get() + locationLut[final] = builder.finalLoc.get() + } + + fun start(vararg expr: Any) { + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") + } + builder.parent.addEntryPoint(builder, exprs) + } + + infix fun String.type(type: Type): VarDecl { + val v = Var(this, type) + builder.addVar(v) + return v + } + + infix fun VarDecl.direction(direction: ParamDirection): VarDecl { + builder.addParam(this, direction) + return this + } + + @XcfaDsl + inner class SequenceLabelContext { + + private val labelList: MutableList = ArrayList() + + infix fun String.assign(to: String): SequenceLabel { + val lhs: VarDecl = + this@XcfaProcedureBuilderContext.builder.lookup(this) as VarDecl + val rhs: Expr = this@XcfaProcedureBuilderContext.builder.parse(to) as Expr + val label = StmtLabel(Assign(lhs, rhs)) + labelList.add(label) + return SequenceLabel(labelList) } - fun start(vararg expr: Any) { - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - builder.parent.addEntryPoint(builder, exprs) + infix fun VarDecl<*>.assign(to: String): SequenceLabel { + val rhs: Expr = this@XcfaProcedureBuilderContext.builder.parse(to) as Expr + val label = StmtLabel(Assign(this as VarDecl, rhs)) + labelList.add(label) + return SequenceLabel(labelList) } - infix fun String.type(type: Type): VarDecl { - val v = Var(this, type) - builder.addVar(v) - return v + infix fun String.assign(to: Expr<*>): SequenceLabel { + val lhs: VarDecl = + this@XcfaProcedureBuilderContext.builder.lookup(this) as VarDecl + val rhs: Expr = to as Expr + val label = StmtLabel(Assign(lhs, rhs)) + labelList.add(label) + return SequenceLabel(labelList) } - infix fun VarDecl.direction(direction: ParamDirection): VarDecl { - builder.addParam(this, direction) - return this + infix fun VarDecl<*>.assign(to: Expr<*>): SequenceLabel { + val rhs: Expr = to as Expr + val label = StmtLabel(Assign(this as VarDecl, rhs)) + labelList.add(label) + return SequenceLabel(labelList) } - @XcfaDsl - inner class SequenceLabelContext { - - private val labelList: MutableList = ArrayList() - - infix fun String.assign(to: String): SequenceLabel { - val lhs: VarDecl = this@XcfaProcedureBuilderContext.builder.lookup( - this) as VarDecl - val rhs: Expr = this@XcfaProcedureBuilderContext.builder.parse(to) as Expr - val label = StmtLabel(Assign(lhs, rhs)) - labelList.add(label) - return SequenceLabel(labelList) - } - - infix fun VarDecl<*>.assign(to: String): SequenceLabel { - val rhs: Expr = this@XcfaProcedureBuilderContext.builder.parse(to) as Expr - val label = StmtLabel(Assign(this as VarDecl, rhs)) - labelList.add(label) - return SequenceLabel(labelList) - } - - infix fun String.assign(to: Expr<*>): SequenceLabel { - val lhs: VarDecl = this@XcfaProcedureBuilderContext.builder.lookup( - this) as VarDecl - val rhs: Expr = to as Expr - val label = StmtLabel(Assign(lhs, rhs)) - labelList.add(label) - return SequenceLabel(labelList) - } - - infix fun VarDecl<*>.assign(to: Expr<*>): SequenceLabel { - val rhs: Expr = to as Expr - val label = StmtLabel(Assign(this as VarDecl, rhs)) - labelList.add(label) - return SequenceLabel(labelList) - } - - fun assume(value: String): SequenceLabel { - val expr = this@XcfaProcedureBuilderContext.builder.parse(value) as Expr - val label = StmtLabel(Assume(expr)) - labelList.add(label) - return SequenceLabel(labelList) - } - - fun assume(expr: Expr): SequenceLabel { - val label = StmtLabel(Assume(expr)) - labelList.add(label) - return SequenceLabel(labelList) - } - - fun havoc(value: String): SequenceLabel { - val varDecl = this@XcfaProcedureBuilderContext.builder.lookup(value) - val label = StmtLabel(Havoc(varDecl)) - labelList.add(label) - return SequenceLabel(labelList) - } + fun assume(value: String): SequenceLabel { + val expr = this@XcfaProcedureBuilderContext.builder.parse(value) as Expr + val label = StmtLabel(Assume(expr)) + labelList.add(label) + return SequenceLabel(labelList) + } - fun havoc(varDecl: VarDecl<*>): SequenceLabel { - val label = StmtLabel(Havoc(varDecl)) - labelList.add(label) - return SequenceLabel(labelList) - } + fun assume(expr: Expr): SequenceLabel { + val label = StmtLabel(Assume(expr)) + labelList.add(label) + return SequenceLabel(labelList) + } - operator fun XcfaProcedureBuilderContext.invoke(vararg expr: Any): SequenceLabel { - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - val label = InvokeLabel(this.builder.name, exprs, EmptyMetaData) - this@SequenceLabelContext.labelList.add(label) - return SequenceLabel(this@SequenceLabelContext.labelList) - } + fun havoc(value: String): SequenceLabel { + val varDecl = this@XcfaProcedureBuilderContext.builder.lookup(value) + val label = StmtLabel(Havoc(varDecl)) + labelList.add(label) + return SequenceLabel(labelList) + } - operator fun String.invoke(vararg expr: Any): SequenceLabel { - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - val label = InvokeLabel(this, exprs, EmptyMetaData) - this@SequenceLabelContext.labelList.add(label) - return SequenceLabel(this@SequenceLabelContext.labelList) - } + fun havoc(varDecl: VarDecl<*>): SequenceLabel { + val label = StmtLabel(Havoc(varDecl)) + labelList.add(label) + return SequenceLabel(labelList) + } - fun String.start(ctx: XcfaProcedureBuilderContext, vararg expr: Any): SequenceLabel { - val lhs = this@XcfaProcedureBuilderContext.builder.lookup(this) - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - val label = StartLabel(ctx.builder.name, exprs, lhs, EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) + operator fun XcfaProcedureBuilderContext.invoke(vararg expr: Any): SequenceLabel { + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") } + val label = InvokeLabel(this.builder.name, exprs, EmptyMetaData) + this@SequenceLabelContext.labelList.add(label) + return SequenceLabel(this@SequenceLabelContext.labelList) + } - fun VarDecl<*>.start(ctx: XcfaProcedureBuilderContext, vararg expr: Any): SequenceLabel { - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - val label = StartLabel(ctx.builder.name, exprs, this, EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) + operator fun String.invoke(vararg expr: Any): SequenceLabel { + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") } + val label = InvokeLabel(this, exprs, EmptyMetaData) + this@SequenceLabelContext.labelList.add(label) + return SequenceLabel(this@SequenceLabelContext.labelList) + } - fun String.start(ctx: String, vararg expr: Any): SequenceLabel { - val lhs = this@XcfaProcedureBuilderContext.builder.lookup(this) - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - val label = StartLabel(ctx, exprs, lhs, EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) + fun String.start(ctx: XcfaProcedureBuilderContext, vararg expr: Any): SequenceLabel { + val lhs = this@XcfaProcedureBuilderContext.builder.lookup(this) + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") } + val label = StartLabel(ctx.builder.name, exprs, lhs, EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) + } - fun VarDecl<*>.start(ctx: String, vararg expr: Any): SequenceLabel { - val exprs = expr.map { - if (it is Expr<*>) it else if (it is String) this@XcfaProcedureBuilderContext.builder.parse( - it) else error("Bad type") - } - val label = StartLabel(ctx, exprs, this, EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) + fun VarDecl<*>.start(ctx: XcfaProcedureBuilderContext, vararg expr: Any): SequenceLabel { + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") } + val label = StartLabel(ctx.builder.name, exprs, this, EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) + } - fun String.join(): SequenceLabel { - val lhs = this@XcfaProcedureBuilderContext.builder.lookup(this) - val label = JoinLabel(lhs, EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) + fun String.start(ctx: String, vararg expr: Any): SequenceLabel { + val lhs = this@XcfaProcedureBuilderContext.builder.lookup(this) + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") } + val label = StartLabel(ctx, exprs, lhs, EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) + } - fun VarDecl<*>.join(): SequenceLabel { - val label = JoinLabel(this, EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) + fun VarDecl<*>.start(ctx: String, vararg expr: Any): SequenceLabel { + val exprs = + expr.map { + if (it is Expr<*>) it + else if (it is String) this@XcfaProcedureBuilderContext.builder.parse(it) + else error("Bad type") } + val label = StartLabel(ctx, exprs, this, EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) + } - fun sequence(lambda: SequenceLabelContext.() -> SequenceLabel): SequenceLabel { - val innerCtx = this@XcfaProcedureBuilderContext.SequenceLabelContext() - val label = lambda(innerCtx) - labelList.add(label) - return SequenceLabel(labelList) - } + fun String.join(): SequenceLabel { + val lhs = this@XcfaProcedureBuilderContext.builder.lookup(this) + val label = JoinLabel(lhs, EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) + } - fun nondet(lambda: SequenceLabelContext.() -> SequenceLabel): SequenceLabel { - val innerCtx = this@XcfaProcedureBuilderContext.SequenceLabelContext() - val label = NondetLabel(lambda(innerCtx).labels.toSet()) - labelList.add(label) - return SequenceLabel(labelList) - } + fun VarDecl<*>.join(): SequenceLabel { + val label = JoinLabel(this, EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) + } - fun fence(vararg content: String): SequenceLabel { - val label = FenceLabel(content.toSet(), EmptyMetaData) - labelList.add(label) - return SequenceLabel(labelList) - } + fun sequence(lambda: SequenceLabelContext.() -> SequenceLabel): SequenceLabel { + val innerCtx = this@XcfaProcedureBuilderContext.SequenceLabelContext() + val label = lambda(innerCtx) + labelList.add(label) + return SequenceLabel(labelList) + } - fun nop(): SequenceLabel { - val label = NopLabel - labelList.add(label) - return SequenceLabel(labelList) - } + fun nondet(lambda: SequenceLabelContext.() -> SequenceLabel): SequenceLabel { + val innerCtx = this@XcfaProcedureBuilderContext.SequenceLabelContext() + val label = NondetLabel(lambda(innerCtx).labels.toSet()) + labelList.add(label) + return SequenceLabel(labelList) + } - fun skip(): SequenceLabel { - return SequenceLabel(labelList) - } + fun fence(vararg content: String): SequenceLabel { + val label = FenceLabel(content.toSet(), EmptyMetaData) + labelList.add(label) + return SequenceLabel(labelList) } - infix fun String.to(to: String): (lambda: SequenceLabelContext.() -> SequenceLabel) -> XcfaEdge { - val loc1 = locationLut.getOrElse(this) { XcfaLocation(this, metadata = EmptyMetaData) } - locationLut.putIfAbsent(this, loc1) - builder.addLoc(loc1) - val loc2 = locationLut.getOrElse(to) { XcfaLocation(to, metadata = EmptyMetaData) } - locationLut.putIfAbsent(to, loc2) - builder.addLoc(loc2) - return { lambda -> - val edge = XcfaEdge(loc1, loc2, lambda(SequenceLabelContext()), EmptyMetaData) - builder.addEdge(edge) - edge - } + fun nop(): SequenceLabel { + val label = NopLabel + labelList.add(label) + return SequenceLabel(labelList) } + fun skip(): SequenceLabel { + return SequenceLabel(labelList) + } + } + + infix fun String.to(to: String): (lambda: SequenceLabelContext.() -> SequenceLabel) -> XcfaEdge { + val loc1 = locationLut.getOrElse(this) { XcfaLocation(this, metadata = EmptyMetaData) } + locationLut.putIfAbsent(this, loc1) + builder.addLoc(loc1) + val loc2 = locationLut.getOrElse(to) { XcfaLocation(to, metadata = EmptyMetaData) } + locationLut.putIfAbsent(to, loc2) + builder.addLoc(loc2) + return { lambda -> + val edge = XcfaEdge(loc1, loc2, lambda(SequenceLabelContext()), EmptyMetaData) + builder.addEdge(edge) + edge + } + } } - fun XcfaBuilder.global(lambda: VarContext.() -> Unit) { - val context = VarContext(this, false) - context.apply(lambda) + val context = VarContext(this, false) + context.apply(lambda) } fun XcfaBuilder.threadlocal(lambda: VarContext.() -> Unit) { - val context = VarContext(this, true) - context.apply(lambda) + val context = VarContext(this, true) + context.apply(lambda) } -fun XcfaBuilder.procedure(name: String, passManager: ProcedurePassManager, - lambda: XcfaProcedureBuilderContext.() -> Unit): XcfaProcedureBuilderContext { - val builder = XcfaProcedureBuilder(name, passManager) - builder.parent = this - val procBuilder = XcfaProcedureBuilderContext(builder).apply(lambda) - this.addProcedure(procBuilder.builder) - return procBuilder +fun XcfaBuilder.procedure( + name: String, + passManager: ProcedurePassManager, + lambda: XcfaProcedureBuilderContext.() -> Unit, +): XcfaProcedureBuilderContext { + val builder = XcfaProcedureBuilder(name, passManager) + builder.parent = this + val procBuilder = XcfaProcedureBuilderContext(builder).apply(lambda) + this.addProcedure(procBuilder.builder) + return procBuilder } -fun XcfaBuilder.procedure(name: String, - lambda: XcfaProcedureBuilderContext.() -> Unit): XcfaProcedureBuilderContext { - return procedure(name, ProcedurePassManager(), lambda) -} \ No newline at end of file +fun XcfaBuilder.procedure( + name: String, + lambda: XcfaProcedureBuilderContext.() -> Unit, +): XcfaProcedureBuilderContext { + return procedure(name, ProcedurePassManager(), lambda) +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt index ea1afc35ac..0b097d5027 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/MetaData.kt @@ -13,24 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.model abstract class MetaData { - abstract fun combine(other: MetaData): MetaData + abstract fun combine(other: MetaData): MetaData } object EmptyMetaData : MetaData() { - // TODO why is this necessary? {@see GsonTest.kt} - private val hash = 123123 + // TODO why is this necessary? {@see GsonTest.kt} + private val hash = 123123 - override fun combine(other: MetaData): MetaData { - return other - } + override fun combine(other: MetaData): MetaData { + return other + } - override fun equals(other: Any?): Boolean = - other is EmptyMetaData + override fun equals(other: Any?): Boolean = other is EmptyMetaData - override fun hashCode(): Int = hash + override fun hashCode(): Int = hash } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt index 91d3d567f2..9e90b22d57 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XCFA.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.model import hu.bme.mit.theta.core.decl.VarDecl @@ -23,132 +22,140 @@ import hu.bme.mit.theta.xcfa.lazyPointsToGraph import java.util.* class XCFA( - val name: String, - val vars: Set, // global variables - val procedureBuilders: Set = emptySet(), - val initProcedureBuilders: List>>> = emptyList() + val name: String, + val vars: Set, // global variables + val procedureBuilders: Set = emptySet(), + val initProcedureBuilders: List>>> = emptyList(), ) { - val pointsToGraph by this.lazyPointsToGraph - - var cachedHash: Int? = null - - var procedures: Set // procedure definitions - private set - - var initProcedures: List>>> // procedure names and parameter assignments - private set - - init { - var phase = 0 - do { - var ready = true - procedureBuilders.forEach { ready = it.optimize(phase) && ready } - initProcedureBuilders.forEach { ready = it.first.optimize(phase) && ready } - phase++ - } while (!ready) - - procedures = procedureBuilders.map { it.build(this) }.toSet() - initProcedures = initProcedureBuilders.map { Pair(it.first.build(this), it.second) } - } - - /** - * Recreate an existing XCFA by substituting the procedures and initProcedures fields. - */ - fun recreate(procedures: Set, initProcedures: List>>>): XCFA { - this.procedures = procedures - this.initProcedures = initProcedures - return this - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as XCFA - - if (name != other.name) return false - if (vars != other.vars) return false - if (procedures != other.procedures) return false - if (initProcedures != other.initProcedures) return false - - return true - } - - override fun hashCode(): Int { - if (cachedHash != null) return cachedHash as Int - var result = name.hashCode() - result = 31 * result + vars.hashCode() - result = 31 * result + procedures.hashCode() - result = 31 * result + initProcedures.hashCode() - cachedHash = result - return result - } - - override fun toString(): String { - return "XCFA(name='$name', vars=$vars, procedures=$procedures, initProcedures=$initProcedures)" - } - - + val pointsToGraph by this.lazyPointsToGraph + + var cachedHash: Int? = null + + var procedures: Set // procedure definitions + private set + + var initProcedures: + List>>> // procedure names and parameter assignments + private set + + init { + var phase = 0 + do { + var ready = true + procedureBuilders.forEach { ready = it.optimize(phase) && ready } + initProcedureBuilders.forEach { ready = it.first.optimize(phase) && ready } + phase++ + } while (!ready) + + procedures = procedureBuilders.map { it.build(this) }.toSet() + initProcedures = initProcedureBuilders.map { Pair(it.first.build(this), it.second) } + } + + /** Recreate an existing XCFA by substituting the procedures and initProcedures fields. */ + fun recreate( + procedures: Set, + initProcedures: List>>>, + ): XCFA { + this.procedures = procedures + this.initProcedures = initProcedures + return this + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as XCFA + + if (name != other.name) return false + if (vars != other.vars) return false + if (procedures != other.procedures) return false + if (initProcedures != other.initProcedures) return false + + return true + } + + override fun hashCode(): Int { + if (cachedHash != null) return cachedHash as Int + var result = name.hashCode() + result = 31 * result + vars.hashCode() + result = 31 * result + procedures.hashCode() + result = 31 * result + initProcedures.hashCode() + cachedHash = result + return result + } + + override fun toString(): String { + return "XCFA(name='$name', vars=$vars, procedures=$procedures, initProcedures=$initProcedures)" + } } data class XcfaProcedure( - val name: String, - val params: List, ParamDirection>>, // procedure params - val vars: Set>, // local variables - val locs: Set, // locations - val edges: Set, // edges - - val initLoc: XcfaLocation, // initial location - val finalLoc: Optional, // final location (optional) - val errorLoc: Optional // error location (optional) + val name: String, + val params: List, ParamDirection>>, // procedure params + val vars: Set>, // local variables + val locs: Set, // locations + val edges: Set, // edges + val initLoc: XcfaLocation, // initial location + val finalLoc: Optional, // final location (optional) + val errorLoc: Optional, // error location (optional) ) { - internal lateinit var parent: XCFA + internal lateinit var parent: XCFA } -data class XcfaLocation @JvmOverloads constructor( - val name: String, // label of the location - val initial: Boolean = false, // is this the initial location? - val final: Boolean = false, // is this the final location? - val error: Boolean = false, // is this the error location? - val metadata: MetaData, +data class XcfaLocation +@JvmOverloads +constructor( + val name: String, // label of the location + val initial: Boolean = false, // is this the initial location? + val final: Boolean = false, // is this the final location? + val error: Boolean = false, // is this the error location? + val metadata: MetaData, ) { - val incomingEdges: MutableSet = LinkedHashSet() // all incoming edges in the current procedure - val outgoingEdges: MutableSet = LinkedHashSet() // all outgoing edges in the current procedure + val incomingEdges: MutableSet = + LinkedHashSet() // all incoming edges in the current procedure + val outgoingEdges: MutableSet = + LinkedHashSet() // all outgoing edges in the current procedure + + companion object { - companion object { + private var cnt: Int = 0 - private var cnt: Int = 0 - fun uniqueCounter(): Int = cnt++ - } + fun uniqueCounter(): Int = cnt++ + } - override fun toString(): String { - return "$name ${if (initial) "{init}" else ""}${if (final) "{final}" else ""}${if (error) "{error}" else ""}" - } + override fun toString(): String { + return "$name ${if (initial) "{init}" else ""}${if (final) "{final}" else ""}${if (error) "{error}" else ""}" + } } data class XcfaEdge( - val source: XcfaLocation, // source location - val target: XcfaLocation, // target location - val label: XcfaLabel = NopLabel, // edge label - val metadata: MetaData + val source: XcfaLocation, // source location + val target: XcfaLocation, // target location + val label: XcfaLabel = NopLabel, // edge label + val metadata: MetaData, ) { - fun withLabel(label: XcfaLabel): XcfaEdge = XcfaEdge(source, target, label, metadata) - fun withTarget(target: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label, metadata) - fun withSource(source: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label, metadata) + fun withLabel(label: XcfaLabel): XcfaEdge = XcfaEdge(source, target, label, metadata) + + fun withTarget(target: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label, metadata) + + fun withSource(source: XcfaLocation): XcfaEdge = XcfaEdge(source, target, label, metadata) } -data class XcfaGlobalVar @JvmOverloads constructor( - val wrappedVar: VarDecl<*>, - val initValue: LitExpr<*>, - val threadLocal: Boolean = false +data class XcfaGlobalVar +@JvmOverloads +constructor( + val wrappedVar: VarDecl<*>, + val initValue: LitExpr<*>, + val threadLocal: Boolean = false, ) enum class ParamDirection { - IN, - OUT, - INOUT + IN, + OUT, + INOUT, } diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt index 0248095a83..b30444ccab 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EliminateSelfLoops.kt @@ -20,22 +20,29 @@ import java.util.stream.Collectors class EliminateSelfLoops : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - val selfLoops: Set = builder.getEdges().stream() - .filter { xcfaEdge -> xcfaEdge.source === xcfaEdge.target }.collect(Collectors.toSet()) - for (selfLoop in selfLoops) { - builder.removeEdge(selfLoop) - val source = selfLoop.source - val target = XcfaLocation(source.name + "_" + XcfaLocation.uniqueCounter(), metadata = EmptyMetaData) - builder.addLoc(target) - for (outgoingEdge in LinkedHashSet(source.outgoingEdges)) { - builder.removeEdge(outgoingEdge) - builder.addEdge(XcfaEdge(target, outgoingEdge.target, outgoingEdge.label, outgoingEdge.metadata)) - } - builder.addEdge(XcfaEdge(source, target, selfLoop.label, selfLoop.metadata)) - builder.addEdge(XcfaEdge(target, source, SequenceLabel(listOf(NopLabel)), selfLoop.metadata)) - } - builder.metaData["noSelfLoops"] = Unit - return builder + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + val selfLoops: Set = + builder + .getEdges() + .stream() + .filter { xcfaEdge -> xcfaEdge.source === xcfaEdge.target } + .collect(Collectors.toSet()) + for (selfLoop in selfLoops) { + builder.removeEdge(selfLoop) + val source = selfLoop.source + val target = + XcfaLocation(source.name + "_" + XcfaLocation.uniqueCounter(), metadata = EmptyMetaData) + builder.addLoc(target) + for (outgoingEdge in LinkedHashSet(source.outgoingEdges)) { + builder.removeEdge(outgoingEdge) + builder.addEdge( + XcfaEdge(target, outgoingEdge.target, outgoingEdge.label, outgoingEdge.metadata) + ) + } + builder.addEdge(XcfaEdge(source, target, selfLoop.label, selfLoop.metadata)) + builder.addEdge(XcfaEdge(target, source, SequenceLabel(listOf(NopLabel)), selfLoop.metadata)) } -} \ No newline at end of file + builder.metaData["noSelfLoops"] = Unit + return builder + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt index 5de0ad72ad..43c29685ee 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/EmptyEdgeRemovalPass.kt @@ -13,48 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.core.stmt.Stmts.Assume import hu.bme.mit.theta.core.type.booltype.BoolExprs.True import hu.bme.mit.theta.xcfa.model.* -/** - * Removes edges that only contain NopLabels (possibly nested) - */ - +/** Removes edges that only contain NopLabels (possibly nested) */ class EmptyEdgeRemovalPass : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - while (true) { - val edge = builder.getEdges().find { - it.label.isNop() && !it.target.error && !it.target.final && !it.source.initial && - (it.source.outgoingEdges.size == 1 || it.target.incomingEdges.size == 1) && - it.metadata is EmptyMetaData - } ?: return builder - val collapseBefore = edge.source.outgoingEdges.size == 1 - builder.removeEdge(edge) - if (collapseBefore) { - val incomingEdges = edge.source.incomingEdges.toList() - incomingEdges.forEach { builder.removeEdge(it) } - incomingEdges.forEach { builder.addEdge(it.withTarget(edge.target)) } - builder.removeLoc(edge.source) - } else { - val outgoingEdges = edge.target.outgoingEdges.toList() - outgoingEdges.forEach { builder.removeEdge(it) } - outgoingEdges.forEach { builder.addEdge(it.withSource(edge.source)) } - builder.removeLoc(edge.target) - } - } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + while (true) { + val edge = + builder.getEdges().find { + it.label.isNop() && + !it.target.error && + !it.target.final && + !it.source.initial && + (it.source.outgoingEdges.size == 1 || it.target.incomingEdges.size == 1) && + it.metadata is EmptyMetaData + } ?: return builder + val collapseBefore = edge.source.outgoingEdges.size == 1 + builder.removeEdge(edge) + if (collapseBefore) { + val incomingEdges = edge.source.incomingEdges.toList() + incomingEdges.forEach { builder.removeEdge(it) } + incomingEdges.forEach { builder.addEdge(it.withTarget(edge.target)) } + builder.removeLoc(edge.source) + } else { + val outgoingEdges = edge.target.outgoingEdges.toList() + outgoingEdges.forEach { builder.removeEdge(it) } + outgoingEdges.forEach { builder.addEdge(it.withSource(edge.source)) } + builder.removeLoc(edge.target) + } } + } - private fun XcfaLabel.isNop(): Boolean = - when (this) { - is NondetLabel -> labels.all { it.isNop() } - is SequenceLabel -> labels.all { it.isNop() } - is NopLabel -> true - is StmtLabel -> stmt == Assume(True()) - else -> false - }.and(metadata is EmptyMetaData) -} \ No newline at end of file + private fun XcfaLabel.isNop(): Boolean = + when (this) { + is NondetLabel -> labels.all { it.isNop() } + is SequenceLabel -> labels.all { it.isNop() } + is NopLabel -> true + is StmtLabel -> stmt == Assume(True()) + else -> false + }.and(metadata is EmptyMetaData) +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt index 0e65bbfc97..5964d29473 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/ErrorLocationPass.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.xcfa.model.* @@ -24,32 +23,37 @@ import hu.bme.mit.theta.xcfa.model.* */ class ErrorLocationPass(private val checkOverflow: Boolean) : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - checkNotNull(builder.metaData["deterministic"]) - for (edge in ArrayList(builder.getEdges())) { - val edges = edge.splitIf(this::predicate) - if (edges.size > 1 || (edges.size == 1 && predicate( - (edges[0].label as SequenceLabel).labels[0]))) { - builder.removeEdge(edge) - edges.forEach { - val label = (it.label as SequenceLabel).labels[0] - if (predicate(label)) { - if (builder.errorLoc.isEmpty) builder.createErrorLoc() - builder.addEdge( - XcfaEdge( - it.source, builder.errorLoc.get(), SequenceLabel(listOf()), metadata = label.metadata - ) - ) - } else { - builder.addEdge(it) - } - } - } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + checkNotNull(builder.metaData["deterministic"]) + for (edge in ArrayList(builder.getEdges())) { + val edges = edge.splitIf(this::predicate) + if ( + edges.size > 1 || + (edges.size == 1 && predicate((edges[0].label as SequenceLabel).labels[0])) + ) { + builder.removeEdge(edge) + edges.forEach { + val label = (it.label as SequenceLabel).labels[0] + if (predicate(label)) { + if (builder.errorLoc.isEmpty) builder.createErrorLoc() + builder.addEdge( + XcfaEdge( + it.source, + builder.errorLoc.get(), + SequenceLabel(listOf()), + metadata = label.metadata, + ) + ) + } else { + builder.addEdge(it) + } } - return builder + } } + return builder + } - private fun predicate(it: XcfaLabel): Boolean { - return it is InvokeLabel && it.name == if (checkOverflow) "overflow" else "reach_error" - } -} \ No newline at end of file + private fun predicate(it: XcfaLabel): Boolean { + return it is InvokeLabel && it.name == if (checkOverflow) "overflow" else "reach_error" + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt index 3effbf99a7..2e776e805b 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FinalLocationPass.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.core.stmt.Stmts @@ -26,38 +25,40 @@ import hu.bme.mit.theta.xcfa.model.* */ class FinalLocationPass(private val checkOverflow: Boolean) : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - checkNotNull(builder.metaData["deterministic"]) - for (edge in ArrayList(builder.getEdges())) { - val edges = edge.splitIf(this::predicate) - if (edges.size > 1 || (edges.size == 1 && predicate( - (edges[0].label as SequenceLabel).labels[0]))) { - builder.removeEdge(edge) - edges.forEach { - if (predicate((it.label as SequenceLabel).labels[0])) { - if (builder.finalLoc.isEmpty) builder.createFinalLoc() - builder.addEdge(XcfaEdge(it.source, builder.finalLoc.get(), SequenceLabel( - listOf( - StmtLabel(Stmts.Assume(BoolExprs.False()), metadata = it.metadata)), - metadata = it.metadata - ), it.metadata - ) - ) - } else { - builder.addEdge(it) - } - } - } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + checkNotNull(builder.metaData["deterministic"]) + for (edge in ArrayList(builder.getEdges())) { + val edges = edge.splitIf(this::predicate) + if ( + edges.size > 1 || + (edges.size == 1 && predicate((edges[0].label as SequenceLabel).labels[0])) + ) { + builder.removeEdge(edge) + edges.forEach { + if (predicate((it.label as SequenceLabel).labels[0])) { + if (builder.finalLoc.isEmpty) builder.createFinalLoc() + builder.addEdge( + XcfaEdge( + it.source, + builder.finalLoc.get(), + SequenceLabel( + listOf(StmtLabel(Stmts.Assume(BoolExprs.False()), metadata = it.metadata)), + metadata = it.metadata, + ), + it.metadata, + ) + ) + } else { + builder.addEdge(it) + } } - return builder + } } + return builder + } - private fun predicate(it: XcfaLabel): Boolean { - val set = - if (checkOverflow) - setOf("abort", "exit", "reach_error") - else - setOf("abort", "exit") - return it is InvokeLabel && set.contains(it.name) - } -} \ No newline at end of file + private fun predicate(it: XcfaLabel): Boolean { + val set = if (checkOverflow) setOf("abort", "exit", "reach_error") else setOf("abort", "exit") + return it is InvokeLabel && set.contains(it.name) + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt index fb8f0d4b31..74d4c53ca9 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/FpFunctionsToExprsPass.kt @@ -32,274 +32,375 @@ import hu.bme.mit.theta.frontend.transformation.model.types.complex.integer.cint import hu.bme.mit.theta.xcfa.model.* import java.util.function.BiFunction -//TODO: type-right conversions (because sqrt and sqrtf might have different domains) +// TODO: type-right conversions (because sqrt and sqrtf might have different domains) class FpFunctionsToExprsPass(val parseContext: ParseContext) : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - checkNotNull(builder.metaData["deterministic"]) - for (edge in ArrayList(builder.getEdges())) { - val newStmts: MutableList = ArrayList() - var found = false - for (stmt in (edge.label as SequenceLabel).labels) { - if (stmt is InvokeLabel) { - if (handlers.containsKey(stmt.name)) { - newStmts.add(checkNotNull(handlers[stmt.name]).apply(builder, stmt)) - found = true - } - } else newStmts.add(stmt) - } - if (found) { - builder.removeEdge(edge) - builder.addEdge(XcfaEdge(edge.source, edge.target, SequenceLabel(newStmts), edge.metadata)) - } - } - return builder + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + checkNotNull(builder.metaData["deterministic"]) + for (edge in ArrayList(builder.getEdges())) { + val newStmts: MutableList = ArrayList() + var found = false + for (stmt in (edge.label as SequenceLabel).labels) { + if (stmt is InvokeLabel) { + if (handlers.containsKey(stmt.name)) { + newStmts.add(checkNotNull(handlers[stmt.name]).apply(builder, stmt)) + found = true + } + } else newStmts.add(stmt) + } + if (found) { + builder.removeEdge(edge) + builder.addEdge(XcfaEdge(edge.source, edge.target, SequenceLabel(newStmts), edge.metadata)) + } } + return builder + } - private val handlers: MutableMap> = LinkedHashMap() - private fun addHandler(names: Array, - handler: BiFunction) { - for (name in names) { - handlers[name] = handler - } - } + private val handlers: + MutableMap> = + LinkedHashMap() - init { - addHandler(arrayOf("fabs", "fabsf", - "fabsl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleFabs(builder, callStmt) - } - addHandler(arrayOf("floor", "floorf", - "floorl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleFloor(builder, callStmt) - } - addHandler(arrayOf("fmax", "fmaxf", - "fmaxl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleFmax(builder, callStmt) - } - addHandler(arrayOf("fmin", "fminf", - "fminl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleFmin(builder, callStmt) - } - addHandler(arrayOf("fmod", "fmodf", - "fmodl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleFmod(builder, callStmt) - } - addHandler(arrayOf("sqrt", "sqrtf", - "sqrtl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleSqrt(builder, callStmt) - } - addHandler(arrayOf("round", "roundf", - "roundl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleRound(builder, callStmt) - } - addHandler(arrayOf("isnan", "__isnan", "isnanf", "__isnanf", "isnanl", - "__isnanl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleIsnan(builder, callStmt) - } - addHandler(arrayOf("trunc")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleTrunc(builder, callStmt) - } - addHandler(arrayOf("ceil")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleCeil(builder, callStmt) - } - addHandler(arrayOf( - "isnormal")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleIsnormal(builder, callStmt) - } - addHandler(arrayOf("isinf", "__isinf", "__isinff", "isinff", - "__isinfl", "isinfl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleIsinf(builder, callStmt) - } - addHandler(arrayOf( - "isfinite", "finite", "isfinitef", "finitef", "isfinite", "finitel", "__finite", "__finitef", "__finitel", - "__isfinite", - "__isfinitef", "__isfinitel")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleIsfinite(builder, callStmt) - } - addHandler(arrayOf("__fpclassify", "__fpclassifyf", - "__fpclassifyl")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> - handleFpclassify(builder, callStmt) - } + private fun addHandler( + names: Array, + handler: BiFunction, + ) { + for (name in names) { + handlers[name] = handler } + } - private fun handleTrunc(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpRoundToIntegralExpr.of(FpRoundingMode.RTZ, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + init { + addHandler(arrayOf("fabs", "fabsf", "fabsl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleFabs(builder, callStmt) } - - private fun handleCeil(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpRoundToIntegralExpr.of(FpRoundingMode.RTP, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + addHandler(arrayOf("floor", "floorf", "floorl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleFloor(builder, callStmt) } - - private fun handleIsinf(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val type = CSignedInt(null, parseContext) - val assign: AssignStmt<*> = Stmts.Assign( - TypeUtils.cast((expr as RefExpr<*>).decl as VarDecl<*>, type.smtType), - TypeUtils.cast(AbstractExprs.Ite( - FpIsInfiniteExpr.of(callStmt.params[1] as Expr), - type.unitValue, type.nullValue), - type.smtType)) - parseContext.metadata.create(assign.expr, "cType", type) - return StmtLabel(assign, metadata = callStmt.metadata) + addHandler(arrayOf("fmax", "fmaxf", "fmaxl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleFmax(builder, callStmt) } - - private fun handleIsfinite(builder: XcfaProcedureBuilder, - callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val type = CSignedInt(null, parseContext) - val assign: AssignStmt<*> = Stmts.Assign( - TypeUtils.cast((expr as RefExpr<*>).decl as VarDecl<*>, type.smtType), - TypeUtils.cast(AbstractExprs.Ite( - Or(FpIsInfiniteExpr.of(callStmt.params[1] as Expr), - FpIsNanExpr.of(callStmt.params[1] as Expr)), - type.nullValue, type.unitValue), - type.smtType)) - parseContext.metadata.create(assign.expr, "cType", type) - return StmtLabel(assign, metadata = callStmt.metadata) + addHandler(arrayOf("fmin", "fminf", "fminl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleFmin(builder, callStmt) } - - private fun handleIsnormal(builder: XcfaProcedureBuilder, - callStmt: InvokeLabel): XcfaLabel { - throw UnsupportedOperationException() + addHandler(arrayOf("fmod", "fmodf", "fmodl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleFmod(builder, callStmt) + } + addHandler(arrayOf("sqrt", "sqrtf", "sqrtl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleSqrt(builder, callStmt) + } + addHandler(arrayOf("round", "roundf", "roundl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleRound(builder, callStmt) + } + addHandler(arrayOf("isnan", "__isnan", "isnanf", "__isnanf", "isnanl", "__isnanl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleIsnan(builder, callStmt) + } + addHandler(arrayOf("trunc")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> + handleTrunc(builder, callStmt) + } + addHandler(arrayOf("ceil")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> + handleCeil(builder, callStmt) } + addHandler(arrayOf("isnormal")) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> + handleIsnormal(builder, callStmt) + } + addHandler(arrayOf("isinf", "__isinf", "__isinff", "isinff", "__isinfl", "isinfl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleIsinf(builder, callStmt) + } + addHandler( + arrayOf( + "isfinite", + "finite", + "isfinitef", + "finitef", + "isfinite", + "finitel", + "__finite", + "__finitef", + "__finitel", + "__isfinite", + "__isfinitef", + "__isfinitel", + ) + ) { builder: XcfaProcedureBuilder, callStmt: InvokeLabel -> + handleIsfinite(builder, callStmt) + } + addHandler(arrayOf("__fpclassify", "__fpclassifyf", "__fpclassifyl")) { + builder: XcfaProcedureBuilder, + callStmt: InvokeLabel -> + handleFpclassify(builder, callStmt) + } + } - private fun handleFpclassify(builder: XcfaProcedureBuilder, - callStmt: InvokeLabel): XcfaLabel { - throw UnsupportedOperationException() + private fun handleTrunc(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpRoundToIntegralExpr.of( + FpRoundingMode.RTZ, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } - private fun handleIsnan(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - val type = CComplexType.getType(expr, parseContext) - val assign: AssignStmt<*> = Stmts.Assign( - TypeUtils.cast((expr as RefExpr<*>).decl as VarDecl<*>, type.smtType), - TypeUtils.cast( - AbstractExprs.Ite( - FpIsNanExpr.of(callStmt.params[1] as Expr), - type.unitValue, type.nullValue), type.smtType)) - parseContext.metadata.create(assign.expr, "cType", type) - return StmtLabel(assign, metadata = callStmt.metadata) - } else { - throw UnsupportedOperationException("Not yet supported without cType") - } + private fun handleCeil(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpRoundToIntegralExpr.of( + FpRoundingMode.RTP, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } + + private fun handleIsinf(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val type = CSignedInt(null, parseContext) + val assign: AssignStmt<*> = + Stmts.Assign( + TypeUtils.cast((expr as RefExpr<*>).decl as VarDecl<*>, type.smtType), + TypeUtils.cast( + AbstractExprs.Ite( + FpIsInfiniteExpr.of(callStmt.params[1] as Expr), + type.unitValue, + type.nullValue, + ), + type.smtType, + ), + ) + parseContext.metadata.create(assign.expr, "cType", type) + return StmtLabel(assign, metadata = callStmt.metadata) + } - private fun handleRound(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpRoundToIntegralExpr.of(FpRoundingMode.RNA, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + private fun handleIsfinite(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val type = CSignedInt(null, parseContext) + val assign: AssignStmt<*> = + Stmts.Assign( + TypeUtils.cast((expr as RefExpr<*>).decl as VarDecl<*>, type.smtType), + TypeUtils.cast( + AbstractExprs.Ite( + Or( + FpIsInfiniteExpr.of(callStmt.params[1] as Expr), + FpIsNanExpr.of(callStmt.params[1] as Expr), + ), + type.nullValue, + type.unitValue, + ), + type.smtType, + ), + ) + parseContext.metadata.create(assign.expr, "cType", type) + return StmtLabel(assign, metadata = callStmt.metadata) + } + + private fun handleIsnormal(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + throw UnsupportedOperationException() + } + + private fun handleFpclassify(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + throw UnsupportedOperationException() + } + + private fun handleIsnan(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + val type = CComplexType.getType(expr, parseContext) + val assign: AssignStmt<*> = + Stmts.Assign( + TypeUtils.cast((expr as RefExpr<*>).decl as VarDecl<*>, type.smtType), + TypeUtils.cast( + AbstractExprs.Ite( + FpIsNanExpr.of(callStmt.params[1] as Expr), + type.unitValue, + type.nullValue, + ), + type.smtType, + ), + ) + parseContext.metadata.create(assign.expr, "cType", type) + return StmtLabel(assign, metadata = callStmt.metadata) + } else { + throw UnsupportedOperationException("Not yet supported without cType") } + } - private fun handleSqrt(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpSqrtExpr.of(FpRoundingMode.RNE, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + private fun handleRound(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpRoundToIntegralExpr.of( + FpRoundingMode.RNA, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } - private fun handleFmod(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - throw UnsupportedOperationException("Fmod not yet supported!") + private fun handleSqrt(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpSqrtExpr.of( + FpRoundingMode.RNE, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } + + private fun handleFmod(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + throw UnsupportedOperationException("Fmod not yet supported!") + } - private fun handleFmin(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 3, - "Function is presumed to be binary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpMinExpr.of(TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[2]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + private fun handleFmin(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 3, "Function is presumed to be binary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpMinExpr.of( + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[2]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } - private fun handleFmax(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 3, - "Function is presumed to be binary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpMaxExpr.of(TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[2]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + private fun handleFmax(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 3, "Function is presumed to be binary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpMaxExpr.of( + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[2]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } - private fun handleFloor(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpRoundToIntegralExpr.of(FpRoundingMode.RTN, - TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + private fun handleFloor(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpRoundToIntegralExpr.of( + FpRoundingMode.RTN, + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr, + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } + return StmtLabel(assign, metadata = callStmt.metadata) + } - private fun handleFabs(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { - Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") - val expr = callStmt.params[0] - Preconditions.checkState(expr is RefExpr<*>) - val assign = Stmts.Assign((expr as RefExpr<*>).decl as VarDecl, - FpAbsExpr.of(TypeUtils.cast(CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), - CComplexType.getType(expr, parseContext).smtType) as Expr)) - if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { - parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) - } - return StmtLabel(assign, metadata = callStmt.metadata) + private fun handleFabs(builder: XcfaProcedureBuilder, callStmt: InvokeLabel): XcfaLabel { + Preconditions.checkState(callStmt.params.size == 2, "Function is presumed to be unary!") + val expr = callStmt.params[0] + Preconditions.checkState(expr is RefExpr<*>) + val assign = + Stmts.Assign( + (expr as RefExpr<*>).decl as VarDecl, + FpAbsExpr.of( + TypeUtils.cast( + CComplexType.getType(expr, parseContext).castTo(callStmt.params[1]), + CComplexType.getType(expr, parseContext).smtType, + ) as Expr + ), + ) + if (parseContext.metadata.getMetadataValue(expr, "cType").isPresent) { + parseContext.metadata.create(assign.expr, "cType", CComplexType.getType(expr, parseContext)) } -} \ No newline at end of file + return StmtLabel(assign, metadata = callStmt.metadata) + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt index 3e1fad28db..aa36b412ad 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/InlineProceduresPass.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.core.decl.VarDecl @@ -25,101 +24,131 @@ import hu.bme.mit.theta.frontend.transformation.model.types.complex.CComplexType import hu.bme.mit.theta.xcfa.model.* /** - * Inlines all procedure invocations in the current procedure. - * Requires the ProcedureBuilder to be `deterministic`. - * Sets the `inlined` flag on the ProcedureBuilder if successful. + * Inlines all procedure invocations in the current procedure. Requires the ProcedureBuilder to be + * `deterministic`. Sets the `inlined` flag on the ProcedureBuilder if successful. */ class InlineProceduresPass(val parseContext: ParseContext) : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - if (!builder.canInline()) return builder - checkNotNull(builder.metaData["deterministic"]) - check(builder.metaData["inlined"] == null) { "Recursive programs are not supported by inlining." } - builder.metaData["inlined"] = Unit - while (true) { - var foundOne = false - for (edge in ArrayList(builder.getEdges())) { - val pred: (XcfaLabel) -> Boolean = { it -> - it is InvokeLabel && builder.parent.getProcedures().any { p -> p.name == it.name } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + if (!builder.canInline()) return builder + checkNotNull(builder.metaData["deterministic"]) + check(builder.metaData["inlined"] == null) { + "Recursive programs are not supported by inlining." + } + builder.metaData["inlined"] = Unit + while (true) { + var foundOne = false + for (edge in ArrayList(builder.getEdges())) { + val pred: (XcfaLabel) -> Boolean = { it -> + it is InvokeLabel && builder.parent.getProcedures().any { p -> p.name == it.name } + } + val edges = edge.splitIf(pred) + if ( + edges.size > 1 || (edges.size == 1 && pred((edges[0].label as SequenceLabel).labels[0])) + ) { + builder.removeEdge(edge) + edges.forEach { e -> + if (pred((e.label as SequenceLabel).labels[0])) { + foundOne = true + val source = e.source + val target = e.target + val invokeLabel: InvokeLabel = e.label.labels[0] as InvokeLabel + val procedure = + builder.parent.getProcedures().find { p -> p.name == invokeLabel.name } + checkNotNull(procedure) + val inlineIndex = + builder.manager.passes.indexOfFirst { phase -> + phase.any { pass -> pass is InlineProceduresPass } } - val edges = edge.splitIf(pred) - if (edges.size > 1 || (edges.size == 1 && pred((edges[0].label as SequenceLabel).labels[0]))) { - builder.removeEdge(edge) - edges.forEach { e -> - if (pred((e.label as SequenceLabel).labels[0])) { - foundOne = true - val source = e.source - val target = e.target - val invokeLabel: InvokeLabel = e.label.labels[0] as InvokeLabel - val procedure = builder.parent.getProcedures().find { p -> p.name == invokeLabel.name } - checkNotNull(procedure) - val inlineIndex = builder.manager.passes.indexOfFirst { phase -> - phase.any { pass -> pass is InlineProceduresPass } - } - procedure.optimize(inlineIndex) + procedure.optimize(inlineIndex) - val newLocs: MutableMap = LinkedHashMap() - procedure.getLocs().forEach { newLocs[it] = it.inlinedCopy() } - procedure.getVars().forEach { builder.addVar(it) } - procedure.getParams().forEach { builder.addVar(it.first) } - procedure.getEdges().forEach { - builder.addEdge(it.withSource(checkNotNull(newLocs[it.source])) - .withTarget(checkNotNull(newLocs[it.target]))) - } + val newLocs: MutableMap = LinkedHashMap() + procedure.getLocs().forEach { newLocs[it] = it.inlinedCopy() } + procedure.getVars().forEach { builder.addVar(it) } + procedure.getParams().forEach { builder.addVar(it.first) } + procedure.getEdges().forEach { + builder.addEdge( + it + .withSource(checkNotNull(newLocs[it.source])) + .withTarget(checkNotNull(newLocs[it.target])) + ) + } - val inStmts: MutableList = ArrayList() - val outStmts: MutableList = ArrayList() - for ((i, param) in procedure.getParams().withIndex()) { - if (param.second != ParamDirection.OUT) { - val stmt = AssignStmt.of(cast(param.first, param.first.type), - cast(CComplexType.getType(param.first.ref, parseContext) - .castTo(invokeLabel.params[i]), param.first.type)) - inStmts.add(StmtLabel(stmt, metadata = invokeLabel.metadata)) - } - - if (param.second != ParamDirection.IN) { - val varDecl = (invokeLabel.params[i] as RefExpr<*>).decl as VarDecl<*> - val stmt = AssignStmt.of(cast(varDecl, param.first.type), cast( - CComplexType.getType(varDecl.ref, parseContext).castTo(param.first.ref), - param.first.type)) - outStmts.add(StmtLabel(stmt, metadata = invokeLabel.metadata)) - } - } + val inStmts: MutableList = ArrayList() + val outStmts: MutableList = ArrayList() + for ((i, param) in procedure.getParams().withIndex()) { + if (param.second != ParamDirection.OUT) { + val stmt = + AssignStmt.of( + cast(param.first, param.first.type), + cast( + CComplexType.getType(param.first.ref, parseContext) + .castTo(invokeLabel.params[i]), + param.first.type, + ), + ) + inStmts.add(StmtLabel(stmt, metadata = invokeLabel.metadata)) + } - val initLoc = procedure.initLoc - val finalLoc = procedure.finalLoc - val errorLoc = procedure.errorLoc + if (param.second != ParamDirection.IN) { + val varDecl = (invokeLabel.params[i] as RefExpr<*>).decl as VarDecl<*> + val stmt = + AssignStmt.of( + cast(varDecl, param.first.type), + cast( + CComplexType.getType(varDecl.ref, parseContext).castTo(param.first.ref), + param.first.type, + ), + ) + outStmts.add(StmtLabel(stmt, metadata = invokeLabel.metadata)) + } + } - builder.addEdge( - XcfaEdge(source, checkNotNull(newLocs[initLoc]), SequenceLabel(inStmts), e.metadata) - ) - if (finalLoc.isPresent) - builder.addEdge(XcfaEdge(checkNotNull(newLocs[finalLoc.get()]), target, - SequenceLabel(outStmts), EmptyMetaData - ) - ) - if (errorLoc.isPresent) { - if (builder.errorLoc.isEmpty) builder.createErrorLoc() - builder.addEdge( - XcfaEdge(checkNotNull(newLocs[errorLoc.get()]), builder.errorLoc.get(), - SequenceLabel(listOf(NopLabel)), EmptyMetaData - ) - ) - } - } else { - builder.addEdge(e) - } + val initLoc = procedure.initLoc + val finalLoc = procedure.finalLoc + val errorLoc = procedure.errorLoc - } - } - } - if (!foundOne) { - return builder + builder.addEdge( + XcfaEdge(source, checkNotNull(newLocs[initLoc]), SequenceLabel(inStmts), e.metadata) + ) + if (finalLoc.isPresent) + builder.addEdge( + XcfaEdge( + checkNotNull(newLocs[finalLoc.get()]), + target, + SequenceLabel(outStmts), + EmptyMetaData, + ) + ) + if (errorLoc.isPresent) { + if (builder.errorLoc.isEmpty) builder.createErrorLoc() + builder.addEdge( + XcfaEdge( + checkNotNull(newLocs[errorLoc.get()]), + builder.errorLoc.get(), + SequenceLabel(listOf(NopLabel)), + EmptyMetaData, + ) + ) + } + } else { + builder.addEdge(e) } + } } + } + if (!foundOne) { + return builder + } } + } - private fun XcfaLocation.inlinedCopy(): XcfaLocation { - return copy(name = name + "_" + XcfaLocation.uniqueCounter(), initial = false, final = false, error = false) - } -} \ No newline at end of file + private fun XcfaLocation.inlinedCopy(): XcfaLocation { + return copy( + name = name + "_" + XcfaLocation.uniqueCounter(), + initial = false, + final = false, + error = false, + ) + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt index 481d019cf0..40e24ad50a 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LbePass.kt @@ -28,294 +28,296 @@ import kotlin.collections.set /** * This pass simplifies the XCFA by joining certain edges to single edges. * - * * Definitions: - * - * * Parallel edges: edges with the same source and target location - * * Snake: a graph component where the incoming and outgoing degree of every location is 1 (except at the ends) - * * Middle location: a location whose incoming degree is 1 - * + * * Parallel edges: edges with the same source and target location + * * Snake: a graph component where the incoming and outgoing degree of every location is 1 (except + * at the ends) + * * Middle location: a location whose incoming degree is 1 */ class LbePass(val parseContext: ParseContext) : ProcedurePass { - companion object { + companion object { - /** - * The level of LBE that specifies which type of graph transformations to apply. - */ - var level = LbeLevel.NO_LBE - } + /** The level of LBE that specifies which type of graph transformations to apply. */ + var level = LbeLevel.NO_LBE + } - /** - * LBE modes. - */ - enum class LbeLevel { + /** LBE modes. */ + enum class LbeLevel { - /** - * The pass returns the builder without applying any changes. - */ - NO_LBE, + /** The pass returns the builder without applying any changes. */ + NO_LBE, - /** - * Applies sequential collapsing on atomic blocks and consecutive local operations. - */ - LBE_LOCAL, - - /** - * Enables collapsing of sequential edges of a location where the number of incoming edges to the location is - * exactly 1. A new edge is created for every outgoing edge of the location combined with the labels of the - * incoming - * edge. Parallel edges are not collapsed. - */ - LBE_SEQ, - - /** - * Enables collapsing of sequential and parallel edges too. - * Currently, [NondetLabel] is not supported by the analysis so this mode cannot be used. - */ - LBE_FULL - } + /** Applies sequential collapsing on atomic blocks and consecutive local operations. */ + LBE_LOCAL, /** - * Stores whether we are in the atomic collapsing phase. - * - * **Warning! Multiple parallel running of this pass instance does not work correctly!** + * Enables collapsing of sequential edges of a location where the number of incoming edges to + * the location is exactly 1. A new edge is created for every outgoing edge of the location + * combined with the labels of the incoming edge. Parallel edges are not collapsed. */ - private var atomicPhase = false - lateinit var builder: XcfaProcedureBuilder + LBE_SEQ, /** - * Steps of graph transformation: - * - * - * 1. Remove outgoing edges of the error location - * 1. Collapse atomic blocks sequentially (with LBE_LOCAL as [LbeLevel] configuration) - * 1. Join parallel edges to single edges and collapse snakes (see Definitions at [LbePass]) - * 1. Collapse sequential edges of locations whose incoming degree is 1, join possibly created parallel edges and - * edge-pairs described in step 2 - * + * Enables collapsing of sequential and parallel edges too. Currently, [NondetLabel] is not + * supported by the analysis so this mode cannot be used. */ - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - if (level == LbeLevel.NO_LBE) return builder + LBE_FULL, + } - if ((level == LbeLevel.LBE_SEQ || level == LbeLevel.LBE_FULL) && parseContext.multiThreading) { - level = LbeLevel.LBE_LOCAL - } + /** + * Stores whether we are in the atomic collapsing phase. + * + * **Warning! Multiple parallel running of this pass instance does not work correctly!** + */ + private var atomicPhase = false + lateinit var builder: XcfaProcedureBuilder - Preconditions.checkNotNull(builder.metaData["deterministic"]) - Preconditions.checkNotNull(builder.metaData["noSelfLoops"]) - this.builder = builder + /** + * Steps of graph transformation: + * 1. Remove outgoing edges of the error location + * 1. Collapse atomic blocks sequentially (with LBE_LOCAL as [LbeLevel] configuration) + * 1. Join parallel edges to single edges and collapse snakes (see Definitions at [LbePass]) + * 1. Collapse sequential edges of locations whose incoming degree is 1, join possibly created + * parallel edges and edge-pairs described in step 2 + */ + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + if (level == LbeLevel.NO_LBE) return builder - // Step 0 - if (builder.errorLoc.isPresent) { - builder.errorLoc.get().outgoingEdges.forEach(builder::removeEdge) - } - - // Step 1 - if (level == LbeLevel.LBE_LOCAL) { - collapseAtomics() - } + if ((level == LbeLevel.LBE_SEQ || level == LbeLevel.LBE_FULL) && parseContext.multiThreading) { + level = LbeLevel.LBE_LOCAL + } - // Step 2 - collapseParallelsAndSnakes(builder.getLocs().toList(), false) + Preconditions.checkNotNull(builder.metaData["deterministic"]) + Preconditions.checkNotNull(builder.metaData["noSelfLoops"]) + this.builder = builder - // Step 3 - //if (level != LbeLevel.LBE_LOCAL) { - removeAllMiddleLocations(builder.getLocs().toList(), false) - //} - return builder + // Step 0 + if (builder.errorLoc.isPresent) { + builder.errorLoc.get().outgoingEdges.forEach(builder::removeEdge) } - /** - * Collapses atomic blocks sequentially. - */ - private fun collapseAtomics() { - atomicPhase = true - val atomicBlockInnerLocations = getAtomicBlockInnerLocations(builder) - collapseParallelsAndSnakes(atomicBlockInnerLocations, true) - removeAllMiddleLocations(atomicBlockInnerLocations, true) - atomicPhase = false + // Step 1 + if (level == LbeLevel.LBE_LOCAL) { + collapseAtomics() } - /** - * Collapses parallel edges and snakes with a starting list of locations to check. Possibly created new parallel - * edges and snakes are collapsed too. - * - * @param locationsToVisit The starting list of locations to check. - * @param strict If true, cascade collapsing is limited to locations in locationsToVisit. - * @return Returns the list of removed locations. - */ - private fun collapseParallelsAndSnakes(locationsToVisit: List, - strict: Boolean): List { - val editedLocationsToVisit = locationsToVisit.toMutableList() - val removedLocations = mutableListOf() - while (editedLocationsToVisit.isNotEmpty()) { - val visiting = editedLocationsToVisit.first() - if (!strict || locationsToVisit.contains(visiting)) { - // Join parallel edges starting from "visiting" location - if (level == LbeLevel.LBE_FULL) { - collapseParallelEdges(visiting, editedLocationsToVisit) - } + // Step 2 + collapseParallelsAndSnakes(builder.getLocs().toList(), false) + + // Step 3 + // if (level != LbeLevel.LBE_LOCAL) { + removeAllMiddleLocations(builder.getLocs().toList(), false) + // } + return builder + } - // Collapse "visiting" location if it is part of a snake - collapsePartOfSnake(visiting, editedLocationsToVisit, removedLocations) - } - editedLocationsToVisit.remove(visiting) + /** Collapses atomic blocks sequentially. */ + private fun collapseAtomics() { + atomicPhase = true + val atomicBlockInnerLocations = getAtomicBlockInnerLocations(builder) + collapseParallelsAndSnakes(atomicBlockInnerLocations, true) + removeAllMiddleLocations(atomicBlockInnerLocations, true) + atomicPhase = false + } + + /** + * Collapses parallel edges and snakes with a starting list of locations to check. Possibly + * created new parallel edges and snakes are collapsed too. + * + * @param locationsToVisit The starting list of locations to check. + * @param strict If true, cascade collapsing is limited to locations in locationsToVisit. + * @return Returns the list of removed locations. + */ + private fun collapseParallelsAndSnakes( + locationsToVisit: List, + strict: Boolean, + ): List { + val editedLocationsToVisit = locationsToVisit.toMutableList() + val removedLocations = mutableListOf() + while (editedLocationsToVisit.isNotEmpty()) { + val visiting = editedLocationsToVisit.first() + if (!strict || locationsToVisit.contains(visiting)) { + // Join parallel edges starting from "visiting" location + if (level == LbeLevel.LBE_FULL) { + collapseParallelEdges(visiting, editedLocationsToVisit) } - return removedLocations + + // Collapse "visiting" location if it is part of a snake + collapsePartOfSnake(visiting, editedLocationsToVisit, removedLocations) + } + editedLocationsToVisit.remove(visiting) } + return removedLocations + } - /** - * Removes locations whose incoming degree is 1. A new edge is created for every outgoing edge of the location - * combined with the labels of the incoming edge as a sequence (the labels of the incoming edge will be the first in - * the sequence). - * - * @param locationsToVisit The starting list of locations to check. - * @param strict If true, cascade collapsing is limited to locations in locationsToVisit. - */ - private fun removeAllMiddleLocations(locationsToVisit: List, strict: Boolean) { - val editedLocationsToVisit = locationsToVisit.toMutableList() - while (editedLocationsToVisit.isNotEmpty()) { - val visiting = editedLocationsToVisit[0] - if (!strict || locationsToVisit.contains(visiting)) { - if (visiting.outgoingEdges.size == 1 && visiting.incomingEdges.size > 1) { - val nextLocation = visiting.outgoingEdges.first().target - val removed = removeMiddleLocation(visiting) - if (removed) { - val start = mutableListOf() - start.add(nextLocation) - val locationsToRemove = collapseParallelsAndSnakes(start, strict) - locationsToRemove.forEach { editedLocationsToVisit.remove(it) } - } - } - } - editedLocationsToVisit.remove(visiting) + /** + * Removes locations whose incoming degree is 1. A new edge is created for every outgoing edge of + * the location combined with the labels of the incoming edge as a sequence (the labels of the + * incoming edge will be the first in the sequence). + * + * @param locationsToVisit The starting list of locations to check. + * @param strict If true, cascade collapsing is limited to locations in locationsToVisit. + */ + private fun removeAllMiddleLocations(locationsToVisit: List, strict: Boolean) { + val editedLocationsToVisit = locationsToVisit.toMutableList() + while (editedLocationsToVisit.isNotEmpty()) { + val visiting = editedLocationsToVisit[0] + if (!strict || locationsToVisit.contains(visiting)) { + if (visiting.outgoingEdges.size == 1 && visiting.incomingEdges.size > 1) { + val nextLocation = visiting.outgoingEdges.first().target + val removed = removeMiddleLocation(visiting) + if (removed) { + val start = mutableListOf() + start.add(nextLocation) + val locationsToRemove = collapseParallelsAndSnakes(start, strict) + locationsToRemove.forEach { editedLocationsToVisit.remove(it) } + } } + } + editedLocationsToVisit.remove(visiting) } + } - /** - * Collapses all parallel edges starting from a location. - * - * @param location the location from where the parallel edges start that we want to remove - * @param locationsToVisit Adds the targets of parallel edges to this list (new parallel edges and snakes - * can appear in these locations) - */ - private fun collapseParallelEdges(location: XcfaLocation, - locationsToVisit: MutableList) { - val edgesByTarget = mutableMapOf>() - for (edge in location.outgoingEdges) { - val edgesToTarget = edgesByTarget.getOrDefault(edge.target, ArrayList()) - edgesToTarget.add(edge) - edgesByTarget[edge.target] = edgesToTarget - } - for (key in edgesByTarget.keys) { - val edgesToTarget: List = checkNotNull(edgesByTarget[key]) - if (edgesToTarget.size <= 1) continue - val source = edgesToTarget[0].source - val target = edgesToTarget[0].target - var nondetLabel = NondetLabel(emptySet()) - for (edge in edgesToTarget) { - val oldLabels = nondetLabel.labels.toMutableSet() - oldLabels.addAll(getNonDetBranch(edge.getFlatLabels())) - nondetLabel = NondetLabel(oldLabels) - builder.removeEdge(edge) - } - builder.addEdge( - XcfaEdge(source, target, nondetLabel, combineMetadata(edgesToTarget.map(XcfaEdge::metadata))) - ) - if (edgesToTarget.size >= 2 && !locationsToVisit.contains(key)) { - locationsToVisit.add(key) - } - } + /** + * Collapses all parallel edges starting from a location. + * + * @param location the location from where the parallel edges start that we want to remove + * @param locationsToVisit Adds the targets of parallel edges to this list (new parallel edges and + * snakes can appear in these locations) + */ + private fun collapseParallelEdges( + location: XcfaLocation, + locationsToVisit: MutableList, + ) { + val edgesByTarget = mutableMapOf>() + for (edge in location.outgoingEdges) { + val edgesToTarget = edgesByTarget.getOrDefault(edge.target, ArrayList()) + edgesToTarget.add(edge) + edgesByTarget[edge.target] = edgesToTarget } + for (key in edgesByTarget.keys) { + val edgesToTarget: List = checkNotNull(edgesByTarget[key]) + if (edgesToTarget.size <= 1) continue + val source = edgesToTarget[0].source + val target = edgesToTarget[0].target + var nondetLabel = NondetLabel(emptySet()) + for (edge in edgesToTarget) { + val oldLabels = nondetLabel.labels.toMutableSet() + oldLabels.addAll(getNonDetBranch(edge.getFlatLabels())) + nondetLabel = NondetLabel(oldLabels) + builder.removeEdge(edge) + } + builder.addEdge( + XcfaEdge( + source, + target, + nondetLabel, + combineMetadata(edgesToTarget.map(XcfaEdge::metadata)), + ) + ) + if (edgesToTarget.size >= 2 && !locationsToVisit.contains(key)) { + locationsToVisit.add(key) + } + } + } - /** - * Collapses the incoming and outgoing edges of a location whose incoming and outgoing degree is 1. - * - * @param location The location to collapse - * @param locationsToVisit The change list, the location that is the source of the incoming edge of the location is - * added to this list - * @param removedLocations The list of removed locations: the collapsed location is added to this list - */ - private fun collapsePartOfSnake(location: XcfaLocation, - locationsToVisit: MutableList, removedLocations: MutableList) { - if (location.incomingEdges.size == 1 && location.outgoingEdges.size == 1) { - val previousLocation = location.incomingEdges.first().source - val removed = removeMiddleLocation(location) - if (removed) removedLocations.add(location) - if (previousLocation !in locationsToVisit) { - locationsToVisit.add(previousLocation) - } - } + /** + * Collapses the incoming and outgoing edges of a location whose incoming and outgoing degree + * is 1. + * + * @param location The location to collapse + * @param locationsToVisit The change list, the location that is the source of the incoming edge + * of the location is added to this list + * @param removedLocations The list of removed locations: the collapsed location is added to this + * list + */ + private fun collapsePartOfSnake( + location: XcfaLocation, + locationsToVisit: MutableList, + removedLocations: MutableList, + ) { + if (location.incomingEdges.size == 1 && location.outgoingEdges.size == 1) { + val previousLocation = location.incomingEdges.first().source + val removed = removeMiddleLocation(location) + if (removed) removedLocations.add(location) + if (previousLocation !in locationsToVisit) { + locationsToVisit.add(previousLocation) + } } + } - /** - * Wraps edge labels to a [SequenceLabel] if the edge does not have - * exactly one label. If the labels contain one [NondetLabel], the - * NondetLabel's labels are returned to simplify the formula. - * - * @param edgeLabels the edge labels we would like to add to the NonDetLabel - * @return the list of labels to add to the NonDetLabel - */ - private fun getNonDetBranch(edgeLabels: List): Set { - if (edgeLabels.size == 1) { - return if (edgeLabels[0] is NondetLabel) { - (edgeLabels[0] as NondetLabel).labels - } else edgeLabels.toSet() - } - return setOf(SequenceLabel(edgeLabels)) + /** + * Wraps edge labels to a [SequenceLabel] if the edge does not have exactly one label. If the + * labels contain one [NondetLabel], the NondetLabel's labels are returned to simplify the + * formula. + * + * @param edgeLabels the edge labels we would like to add to the NonDetLabel + * @return the list of labels to add to the NonDetLabel + */ + private fun getNonDetBranch(edgeLabels: List): Set { + if (edgeLabels.size == 1) { + return if (edgeLabels[0] is NondetLabel) { + (edgeLabels[0] as NondetLabel).labels + } else edgeLabels.toSet() } + return setOf(SequenceLabel(edgeLabels)) + } - /** - * Removes a location whose outgoing degree is 1. A new edge is created for every incoming edge of the location - * combined with the labels of the outgoing edge as a sequence (the labels of the incoming edge will be the first in - * the sequence). - * - * @param location The location to remove - */ - private fun removeMiddleLocation(location: XcfaLocation): Boolean { - if (location.outgoingEdges.size != 1) return false - val outEdge = location.outgoingEdges.first() - if ( - location.incomingEdges.any { edge -> edge.getFlatLabels().any { it is InvokeLabel } } - || location.outgoingEdges.any { edge -> edge.getFlatLabels().any { it is InvokeLabel } } - || (level == LbeLevel.LBE_LOCAL && !atomicPhase && isNotLocal(outEdge)) - ) { - return false - } + /** + * Removes a location whose outgoing degree is 1. A new edge is created for every incoming edge of + * the location combined with the labels of the outgoing edge as a sequence (the labels of the + * incoming edge will be the first in the sequence). + * + * @param location The location to remove + */ + private fun removeMiddleLocation(location: XcfaLocation): Boolean { + if (location.outgoingEdges.size != 1) return false + val outEdge = location.outgoingEdges.first() + if ( + location.incomingEdges.any { edge -> edge.getFlatLabels().any { it is InvokeLabel } } || + location.outgoingEdges.any { edge -> edge.getFlatLabels().any { it is InvokeLabel } } || + (level == LbeLevel.LBE_LOCAL && !atomicPhase && isNotLocal(outEdge)) + ) { + return false + } - builder.removeEdge(outEdge) - builder.removeLoc(location) - val edgesToRemove = location.incomingEdges.toSet() - for (inEdge in edgesToRemove) { - builder.removeEdge(inEdge) - val newLabels = mutableListOf() - newLabels.addAll(inEdge.getFlatLabels()) - newLabels.addAll(outEdge.getFlatLabels()) - builder.addEdge( - XcfaEdge( - inEdge.source, outEdge.target, SequenceLabel(newLabels), - combineMetadata(inEdge.metadata, outEdge.metadata) - ) - ) - } - return true + builder.removeEdge(outEdge) + builder.removeLoc(location) + val edgesToRemove = location.incomingEdges.toSet() + for (inEdge in edgesToRemove) { + builder.removeEdge(inEdge) + val newLabels = mutableListOf() + newLabels.addAll(inEdge.getFlatLabels()) + newLabels.addAll(outEdge.getFlatLabels()) + builder.addEdge( + XcfaEdge( + inEdge.source, + outEdge.target, + SequenceLabel(newLabels), + combineMetadata(inEdge.metadata, outEdge.metadata), + ) + ) } + return true + } - /** - * Determines whether an edge performs only local operations or not (thread start and join operations are not - * considered local here). - * - * @param edge the edge whose "locality" is to be determined - * @return true, if the edge performs at least one non-local operation - */ - private fun isNotLocal(edge: XcfaEdge): Boolean { - return !edge.getFlatLabels().all { label -> - !(label is StartLabel || label is JoinLabel) && label.collectVars().all(builder.getVars()::contains) && - !(label is StmtLabel && label.stmt is AssumeStmt && label.stmt.cond is FalseExpr) && - !(label is FenceLabel && label.labels.any { name -> - listOf("ATOMIC_BEGIN", "mutex_lock", "cond_wait").any { name.startsWith(it) } - }) - } + /** + * Determines whether an edge performs only local operations or not (thread start and join + * operations are not considered local here). + * + * @param edge the edge whose "locality" is to be determined + * @return true, if the edge performs at least one non-local operation + */ + private fun isNotLocal(edge: XcfaEdge): Boolean { + return !edge.getFlatLabels().all { label -> + !(label is StartLabel || label is JoinLabel) && + label.collectVars().all(builder.getVars()::contains) && + !(label is StmtLabel && label.stmt is AssumeStmt && label.stmt.cond is FalseExpr) && + !(label is FenceLabel && + label.labels.any { name -> + listOf("ATOMIC_BEGIN", "mutex_lock", "cond_wait").any { name.startsWith(it) } + }) } -} \ No newline at end of file + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt index 0c34b94caa..52757d4551 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/LoopUnrollPass.kt @@ -33,276 +33,300 @@ import hu.bme.mit.theta.xcfa.model.* import java.util.* /** - * Unrolls loops where the number of loop executions can be determined statically. - * The UNROLL_LIMIT refers to the number of loop executions: loops that are executed more times than this limit - * are not unrolled. Loops with unknown number of iterations are unrolled to FORCE_UNROLL_LIMIT iterations (this - * way a safe result might not be valid). + * Unrolls loops where the number of loop executions can be determined statically. The UNROLL_LIMIT + * refers to the number of loop executions: loops that are executed more times than this limit are + * not unrolled. Loops with unknown number of iterations are unrolled to FORCE_UNROLL_LIMIT + * iterations (this way a safe result might not be valid). */ class LoopUnrollPass : ProcedurePass { - companion object { + companion object { - var UNROLL_LIMIT = 1000 - var FORCE_UNROLL_LIMIT = -1 - var FORCE_UNROLL_USED = false + var UNROLL_LIMIT = 1000 + var FORCE_UNROLL_LIMIT = -1 + var FORCE_UNROLL_USED = false - private val solver: Solver = Z3SolverFactory.getInstance().createSolver() - } + private val solver: Solver = Z3SolverFactory.getInstance().createSolver() + } - private val testedLoops = mutableSetOf() + private val testedLoops = mutableSetOf() - private data class Loop( - val loopStart: XcfaLocation, val loopLocs: Set, val loopEdges: Set, - val loopVar: VarDecl<*>?, val loopVarInit: XcfaEdge?, val loopVarModifiers: List?, - val loopStartEdges: List, val exitEdges: Map>, - val properlyUnrollable: Boolean - ) { + private data class Loop( + val loopStart: XcfaLocation, + val loopLocs: Set, + val loopEdges: Set, + val loopVar: VarDecl<*>?, + val loopVarInit: XcfaEdge?, + val loopVarModifiers: List?, + val loopStartEdges: List, + val exitEdges: Map>, + val properlyUnrollable: Boolean, + ) { - private class BasicStmtAction(private val stmt: Stmt) : StmtAction() { - constructor(edge: XcfaEdge) : this(edge.label.toStmt()) - constructor(edges: List) : this(SequenceLabel(edges.map { it.label }).toStmt()) + private class BasicStmtAction(private val stmt: Stmt) : StmtAction() { + constructor(edge: XcfaEdge) : this(edge.label.toStmt()) - override fun getStmts() = listOf(stmt) - } + constructor(edges: List) : this(SequenceLabel(edges.map { it.label }).toStmt()) - fun unroll(builder: XcfaProcedureBuilder, transFunc: ExplStmtTransFunc) { - val count = count(transFunc) - if (count != null) { - unroll(builder, count, true) - } else if (FORCE_UNROLL_LIMIT != -1) { - FORCE_UNROLL_USED = true - unroll(builder, FORCE_UNROLL_LIMIT, false) - } - } + override fun getStmts() = listOf(stmt) + } - fun unroll(builder: XcfaProcedureBuilder, count: Int, removeCond: Boolean) { - (loopLocs - loopStart).forEach(builder::removeLoc) - loopLocs.flatMap { it.outgoingEdges }.forEach(builder::removeEdge) + fun unroll(builder: XcfaProcedureBuilder, transFunc: ExplStmtTransFunc) { + val count = count(transFunc) + if (count != null) { + unroll(builder, count, true) + } else if (FORCE_UNROLL_LIMIT != -1) { + FORCE_UNROLL_USED = true + unroll(builder, FORCE_UNROLL_LIMIT, false) + } + } - var startLocation = loopStart - for (i in 0 until count) { - startLocation = copyBody(builder, startLocation, i, removeCond) - } + fun unroll(builder: XcfaProcedureBuilder, count: Int, removeCond: Boolean) { + (loopLocs - loopStart).forEach(builder::removeLoc) + loopLocs.flatMap { it.outgoingEdges }.forEach(builder::removeEdge) - exitEdges[loopStart]?.forEach { edge -> - val label = if (removeCond) edge.label.removeCondition() else edge.label - builder.addEdge(XcfaEdge(startLocation, edge.target, label, edge.metadata)) - } - } + var startLocation = loopStart + for (i in 0 until count) { + startLocation = copyBody(builder, startLocation, i, removeCond) + } - private fun count(transFunc: ExplStmtTransFunc): Int? { - if (!properlyUnrollable) return null - check(loopVar != null && loopVarModifiers != null && loopVarInit != null) - check(loopStartEdges.size == 1) - - val prec = ExplPrec.of(listOf(loopVar)) - var state = ExplState.of(ImmutableValuation.empty()) - state = transFunc.getSuccStates(state, BasicStmtAction(loopVarInit), prec).first() - - var cnt = 0 - val loopCondAction = BasicStmtAction(loopStartEdges.first()) - while (!transFunc.getSuccStates(state, loopCondAction, prec).first().isBottom) { - cnt++ - if (UNROLL_LIMIT in 0 until cnt) return null - state = transFunc.getSuccStates(state, BasicStmtAction(loopVarModifiers), prec).first() - } - return cnt - } - - private fun copyBody(builder: XcfaProcedureBuilder, startLoc: XcfaLocation, index: Int, removeCond: Boolean) - : XcfaLocation { - val locs = loopLocs.associateWith { - val loc = XcfaLocation("${it.name}_loop${index}", metadata = it.metadata) - builder.addLoc(loc) - loc - } - - loopEdges.forEach { - val newSource = if (it.source == loopStart) startLoc else locs[it.source]!! - val newLabel = if (it.source == loopStart && removeCond) it.label.removeCondition() else it.label - val edge = XcfaEdge(newSource, locs[it.target]!!, newLabel, it.metadata) - builder.addEdge(edge) - } + exitEdges[loopStart]?.forEach { edge -> + val label = if (removeCond) edge.label.removeCondition() else edge.label + builder.addEdge(XcfaEdge(startLocation, edge.target, label, edge.metadata)) + } + } - exitEdges.forEach { (loc, edges) -> - for (edge in edges) { - if (removeCond && loc == loopStart) continue - val source = if (loc == loopStart) startLoc else locs[loc]!! - builder.addEdge(XcfaEdge(source, edge.target, edge.label, edge.metadata)) - } - } + private fun count(transFunc: ExplStmtTransFunc): Int? { + if (!properlyUnrollable) return null + check(loopVar != null && loopVarModifiers != null && loopVarInit != null) + check(loopStartEdges.size == 1) + + val prec = ExplPrec.of(listOf(loopVar)) + var state = ExplState.of(ImmutableValuation.empty()) + state = transFunc.getSuccStates(state, BasicStmtAction(loopVarInit), prec).first() + + var cnt = 0 + val loopCondAction = BasicStmtAction(loopStartEdges.first()) + while (!transFunc.getSuccStates(state, loopCondAction, prec).first().isBottom) { + cnt++ + if (UNROLL_LIMIT in 0 until cnt) return null + state = transFunc.getSuccStates(state, BasicStmtAction(loopVarModifiers), prec).first() + } + return cnt + } - return locs[loopStart]!! + private fun copyBody( + builder: XcfaProcedureBuilder, + startLoc: XcfaLocation, + index: Int, + removeCond: Boolean, + ): XcfaLocation { + val locs = + loopLocs.associateWith { + val loc = XcfaLocation("${it.name}_loop${index}", metadata = it.metadata) + builder.addLoc(loc) + loc } - private fun XcfaLabel.removeCondition(): XcfaLabel { - val stmtToRemove = getFlatLabels().find { - it is StmtLabel && it.stmt is AssumeStmt && (it.collectVars() - loopVar).isEmpty() - } - return when { - this == stmtToRemove -> NopLabel - this is SequenceLabel -> SequenceLabel(labels.map { it.removeCondition() }, metadata) - else -> this - } + loopEdges.forEach { + val newSource = if (it.source == loopStart) startLoc else locs[it.source]!! + val newLabel = + if (it.source == loopStart && removeCond) it.label.removeCondition() else it.label + val edge = XcfaEdge(newSource, locs[it.target]!!, newLabel, it.metadata) + builder.addEdge(edge) + } + + exitEdges.forEach { (loc, edges) -> + for (edge in edges) { + if (removeCond && loc == loopStart) continue + val source = if (loc == loopStart) startLoc else locs[loc]!! + builder.addEdge(XcfaEdge(source, edge.target, edge.label, edge.metadata)) } + } + + return locs[loopStart]!! } - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - val transFunc = ExplStmtTransFunc.create(solver, 1) - while (true) { - val loop = findLoop(builder.initLoc) ?: break - loop.unroll(builder, transFunc) - testedLoops.add(loop) + private fun XcfaLabel.removeCondition(): XcfaLabel { + val stmtToRemove = + getFlatLabels().find { + it is StmtLabel && it.stmt is AssumeStmt && (it.collectVars() - loopVar).isEmpty() } - return builder + return when { + this == stmtToRemove -> NopLabel + this is SequenceLabel -> SequenceLabel(labels.map { it.removeCondition() }, metadata) + else -> this + } } - - private fun findLoop(initLoc: XcfaLocation): Loop? { // DFS - val stack = Stack() - val explored = mutableSetOf() - stack.push(initLoc) - while (stack.isNotEmpty()) { - val current = stack.peek() - val edgesToExplore = current.outgoingEdges subtract explored - if (edgesToExplore.isEmpty()) { - stack.pop() - } else { - val edge = edgesToExplore.random() - if (edge.target in stack) { // loop found - getLoop(edge.target)?.let { return it } - } else { - stack.push(edge.target) - } - explored.add(edge) - } + } + + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + val transFunc = ExplStmtTransFunc.create(solver, 1) + while (true) { + val loop = findLoop(builder.initLoc) ?: break + loop.unroll(builder, transFunc) + testedLoops.add(loop) + } + return builder + } + + private fun findLoop(initLoc: XcfaLocation): Loop? { // DFS + val stack = Stack() + val explored = mutableSetOf() + stack.push(initLoc) + while (stack.isNotEmpty()) { + val current = stack.peek() + val edgesToExplore = current.outgoingEdges subtract explored + if (edgesToExplore.isEmpty()) { + stack.pop() + } else { + val edge = edgesToExplore.random() + if (edge.target in stack) { // loop found + getLoop(edge.target)?.let { + return it + } + } else { + stack.push(edge.target) } - return null + explored.add(edge) + } + } + return null + } + + /** Find a loop from the given start location that can be unrolled. */ + private fun getLoop(loopStart: XcfaLocation): Loop? { + var properlyUnrollable = true + if (loopStart.outgoingEdges.size != 2) { + properlyUnrollable = false // more than two outgoing edges from the loop start not supported } - /** - * Find a loop from the given start location that can be unrolled. - */ - private fun getLoop(loopStart: XcfaLocation): Loop? { - var properlyUnrollable = true - if (loopStart.outgoingEdges.size != 2) { - properlyUnrollable = false // more than two outgoing edges from the loop start not supported + val (loopLocations, loopEdges) = getLoopElements(loopStart) + if (loopEdges.isEmpty()) return null // unsupported loop structure + + val loopCondEdges = loopStart.outgoingEdges.filter { it.target in loopLocations } + if (loopCondEdges.size != 1) + properlyUnrollable = false // more than one loop condition not supported + + // find the loop variable based on the outgoing edges from the loop start location + val loopVar = + loopStart.outgoingEdges + .map { + val vars = it.label.collectVarsWithAccessType() + if (vars.size != 1) { + null // multiple variables in the loop condition not supported + } else { + vars.keys.first() + } + } + .reduce { v1, v2 -> if (v1 != v2) null else v1 } + if (loopVar == null) properlyUnrollable = false + + val (loopVarInit, loopVarModifiers) = + run { + if (!properlyUnrollable) return@run null + + // find (a subset of) edges that are executed in every loop iteration + var edge = loopStart.outgoingEdges.find { it.target in loopLocations }!! + val necessaryLoopEdges = mutableSetOf(edge) + while (edge.target.outgoingEdges.size == 1) { + edge = edge.target.outgoingEdges.first() + necessaryLoopEdges.add(edge) + } + val finalEdges = loopStart.incomingEdges.filter { it.source in loopLocations } + if (finalEdges.size == 1) { + edge = finalEdges.first() + necessaryLoopEdges.add(edge) + while (edge.source.incomingEdges.size == 1) { + edge = edge.source.incomingEdges.first() + necessaryLoopEdges.add(edge) + } } - val (loopLocations, loopEdges) = getLoopElements(loopStart) - if (loopEdges.isEmpty()) return null // unsupported loop structure - - val loopCondEdges = loopStart.outgoingEdges.filter { it.target in loopLocations } - if (loopCondEdges.size != 1) properlyUnrollable = false // more than one loop condition not supported - - // find the loop variable based on the outgoing edges from the loop start location - val loopVar = loopStart.outgoingEdges.map { + // find edges that modify the loop variable + val loopVarModifiers = + loopEdges.filter { val vars = it.label.collectVarsWithAccessType() - if (vars.size != 1) { - null // multiple variables in the loop condition not supported + if (vars[loopVar].isWritten) { + if (it !in necessaryLoopEdges || vars.size > 1) + return@run null // loop variable modification cannot be determined statically + true } else { - vars.keys.first() - } - }.reduce { v1, v2 -> if (v1 != v2) null else v1 } - if (loopVar == null) properlyUnrollable = false - - val (loopVarInit, loopVarModifiers) = run { - if (!properlyUnrollable) return@run null - - // find (a subset of) edges that are executed in every loop iteration - var edge = loopStart.outgoingEdges.find { it.target in loopLocations }!! - val necessaryLoopEdges = mutableSetOf(edge) - while (edge.target.outgoingEdges.size == 1) { - edge = edge.target.outgoingEdges.first() - necessaryLoopEdges.add(edge) - } - val finalEdges = loopStart.incomingEdges.filter { it.source in loopLocations } - if (finalEdges.size == 1) { - edge = finalEdges.first() - necessaryLoopEdges.add(edge) - while (edge.source.incomingEdges.size == 1) { - edge = edge.source.incomingEdges.first() - necessaryLoopEdges.add(edge) - } - } - - // find edges that modify the loop variable - val loopVarModifiers = loopEdges.filter { - val vars = it.label.collectVarsWithAccessType() - if (vars[loopVar].isWritten) { - if (it !in necessaryLoopEdges || vars.size > 1) return@run null // loop variable modification cannot be determined statically - true - } else { - false - } - } - - // find loop variable initialization before the loop - lateinit var loopVarInit: XcfaEdge - var loc = loopStart - while (true) { - val inEdges = loc.incomingEdges.filter { it.source !in loopLocations } - if (inEdges.size != 1) return@run null - val inEdge = inEdges.first() - val vars = inEdge.label.collectVarsWithAccessType() - if (vars[loopVar].isWritten) { - if (vars.size > 1) return@run null - loopVarInit = inEdge - break - } - loc = inEdge.source + false } + } - loopVarInit to loopVarModifiers - } ?: run { - properlyUnrollable = false - null to null + // find loop variable initialization before the loop + lateinit var loopVarInit: XcfaEdge + var loc = loopStart + while (true) { + val inEdges = loc.incomingEdges.filter { it.source !in loopLocations } + if (inEdges.size != 1) return@run null + val inEdge = inEdges.first() + val vars = inEdge.label.collectVarsWithAccessType() + if (vars[loopVar].isWritten) { + if (vars.size > 1) return@run null + loopVarInit = inEdge + break + } + loc = inEdge.source } - val exits = loopLocations.mapNotNull { loc -> - val exitEdges = loc.outgoingEdges.filter { it.target !in loopLocations } - if (exitEdges.isEmpty()) null else (loc to exitEdges) - }.toMap() - return Loop( - loopStart = loopStart, - loopLocs = loopLocations, - loopEdges = loopEdges, - loopVar = loopVar, - loopVarInit = loopVarInit, - loopVarModifiers = loopVarModifiers, - loopStartEdges = loopCondEdges, - exitEdges = exits, - properlyUnrollable = properlyUnrollable, - ).also { if (it in testedLoops) return null } - } - - /** - * Find loop locations and edges. - */ - private fun getLoopElements(loopStart: XcfaLocation): Pair, Set> { - val backSearch: (XcfaLocation) -> Pair, List>? = backSearch@{ startLoc -> - val locs = mutableSetOf() - val edges = mutableListOf() - val toVisit = mutableListOf(startLoc) - while (toVisit.isNotEmpty()) { - val current = toVisit.removeFirst() - if (current == loopStart) continue - if (current.incomingEdges.size == 0) return@backSearch null // not part of the loop - if (locs.add(current)) { - edges.addAll(current.incomingEdges) - toVisit.addAll(current.incomingEdges.map { it.source }) - } - } - locs to edges + loopVarInit to loopVarModifiers + } + ?: run { + properlyUnrollable = false + null to null } - val locs = mutableSetOf(loopStart) - val edges = mutableSetOf() - loopStart.incomingEdges.forEach { incoming -> - val (l, e) = backSearch(incoming.source) ?: return@forEach - locs.addAll(l) - edges.addAll(e) - edges.add(incoming) + val exits = + loopLocations + .mapNotNull { loc -> + val exitEdges = loc.outgoingEdges.filter { it.target !in loopLocations } + if (exitEdges.isEmpty()) null else (loc to exitEdges) + } + .toMap() + return Loop( + loopStart = loopStart, + loopLocs = loopLocations, + loopEdges = loopEdges, + loopVar = loopVar, + loopVarInit = loopVarInit, + loopVarModifiers = loopVarModifiers, + loopStartEdges = loopCondEdges, + exitEdges = exits, + properlyUnrollable = properlyUnrollable, + ) + .also { if (it in testedLoops) return null } + } + + /** Find loop locations and edges. */ + private fun getLoopElements(loopStart: XcfaLocation): Pair, Set> { + val backSearch: (XcfaLocation) -> Pair, List>? = + backSearch@{ startLoc -> + val locs = mutableSetOf() + val edges = mutableListOf() + val toVisit = mutableListOf(startLoc) + while (toVisit.isNotEmpty()) { + val current = toVisit.removeFirst() + if (current == loopStart) continue + if (current.incomingEdges.size == 0) return@backSearch null // not part of the loop + if (locs.add(current)) { + edges.addAll(current.incomingEdges) + toVisit.addAll(current.incomingEdges.map { it.source }) + } } - return locs to edges + locs to edges + } + + val locs = mutableSetOf(loopStart) + val edges = mutableSetOf() + loopStart.incomingEdges.forEach { incoming -> + val (l, e) = backSearch(incoming.source) ?: return@forEach + locs.addAll(l) + edges.addAll(e) + edges.add(incoming) } -} \ No newline at end of file + return locs to edges + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt index c505d0e99b..0ee0c65b9d 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/MallocFunctionPass.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.core.decl.Decls.Var @@ -31,63 +30,88 @@ import hu.bme.mit.theta.xcfa.model.* import org.abego.treelayout.internal.util.Contract.checkState /** - * Transforms mallocs into address assignments. - * Requires the ProcedureBuilder be `deterministic`. + * Transforms mallocs into address assignments. Requires the ProcedureBuilder be `deterministic`. */ class MallocFunctionPass(val parseContext: ParseContext) : ProcedurePass { - private val XcfaBuilder.malloc: VarDecl<*> by lazy { - Var("__malloc", CPointer(null, null, parseContext).smtType) - } + private val XcfaBuilder.malloc: VarDecl<*> by lazy { + Var("__malloc", CPointer(null, null, parseContext).smtType) + } - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - checkNotNull(builder.metaData["deterministic"]) - for (edge in ArrayList(builder.getEdges())) { - val edges = edge.splitIf(this::predicate) - if (edges.size > 1 || (edges.size == 1 && predicate( - (edges[0].label as SequenceLabel).labels[0]))) { - builder.removeEdge(edge) - edges.forEach { - if (predicate((it.label as SequenceLabel).labels[0])) { - val invokeLabel = it.label.labels[0] as InvokeLabel - val ret = invokeLabel.params[0] as RefExpr<*> - val mallocVar = builder.parent.malloc - if (builder.parent.getVars().none { it.wrappedVar == mallocVar }) { // initial creation - builder.parent.addVar( - XcfaGlobalVar(mallocVar, CComplexType.getType(ret, parseContext).nullValue)) - val initProc = builder.parent.getInitProcedures().map { it.first } - checkState(initProc.size == 1, "Multiple start procedure are not handled well") - initProc.forEach { - val initAssign = StmtLabel(Assign(cast(mallocVar, mallocVar.type), - cast(CComplexType.getType(ret, parseContext).nullValue, mallocVar.type))) - val newEdges = it.initLoc.outgoingEdges.map { - it.withLabel( - SequenceLabel(listOf(initAssign) + it.label.getFlatLabels(), it.label.metadata)) - } - it.initLoc.outgoingEdges.forEach(it::removeEdge) - newEdges.forEach(it::addEdge) - } - } - val assign1 = AssignStmt.of( - cast(mallocVar, ret.type), - cast(Add(mallocVar.ref, CComplexType.getType(ret, parseContext).getValue("3")), - ret.type)) - val assign2 = AssignStmt.of( - cast(ret.decl as VarDecl<*>, ret.type), cast(mallocVar.ref, ret.type)) - builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel( - listOf( - StmtLabel(assign1, metadata = invokeLabel.metadata), - StmtLabel(assign2, metadata = invokeLabel.metadata))), it.metadata)) - } else { - builder.addEdge(it) - } - } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + checkNotNull(builder.metaData["deterministic"]) + for (edge in ArrayList(builder.getEdges())) { + val edges = edge.splitIf(this::predicate) + if ( + edges.size > 1 || + (edges.size == 1 && predicate((edges[0].label as SequenceLabel).labels[0])) + ) { + builder.removeEdge(edge) + edges.forEach { + if (predicate((it.label as SequenceLabel).labels[0])) { + val invokeLabel = it.label.labels[0] as InvokeLabel + val ret = invokeLabel.params[0] as RefExpr<*> + val mallocVar = builder.parent.malloc + if (builder.parent.getVars().none { it.wrappedVar == mallocVar }) { // initial creation + builder.parent.addVar( + XcfaGlobalVar(mallocVar, CComplexType.getType(ret, parseContext).nullValue) + ) + val initProc = builder.parent.getInitProcedures().map { it.first } + checkState(initProc.size == 1, "Multiple start procedure are not handled well") + initProc.forEach { + val initAssign = + StmtLabel( + Assign( + cast(mallocVar, mallocVar.type), + cast(CComplexType.getType(ret, parseContext).nullValue, mallocVar.type), + ) + ) + val newEdges = + it.initLoc.outgoingEdges.map { + it.withLabel( + SequenceLabel( + listOf(initAssign) + it.label.getFlatLabels(), + it.label.metadata, + ) + ) + } + it.initLoc.outgoingEdges.forEach(it::removeEdge) + newEdges.forEach(it::addEdge) + } } + val assign1 = + AssignStmt.of( + cast(mallocVar, ret.type), + cast( + Add(mallocVar.ref, CComplexType.getType(ret, parseContext).getValue("3")), + ret.type, + ), + ) + val assign2 = + AssignStmt.of(cast(ret.decl as VarDecl<*>, ret.type), cast(mallocVar.ref, ret.type)) + builder.addEdge( + XcfaEdge( + it.source, + it.target, + SequenceLabel( + listOf( + StmtLabel(assign1, metadata = invokeLabel.metadata), + StmtLabel(assign2, metadata = invokeLabel.metadata), + ) + ), + it.metadata, + ) + ) + } else { + builder.addEdge(it) + } } - return builder + } } + return builder + } - private fun predicate(it: XcfaLabel): Boolean { - return it is InvokeLabel && it.name == "malloc" - } -} \ No newline at end of file + private fun predicate(it: XcfaLabel): Boolean { + return it is InvokeLabel && it.name == "malloc" + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt index 2737d1dbb1..c5e531a058 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NoSideEffectPass.kt @@ -13,42 +13,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.frontend.ParseContext import hu.bme.mit.theta.xcfa.model.* /** - * Transforms all ignored calls into nop/skip labels. - * Requires the ProcedureBuilder be `deterministic`. + * Transforms all ignored calls into nop/skip labels. Requires the ProcedureBuilder be + * `deterministic`. */ class NoSideEffectPass(val parseContext: ParseContext) : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - checkNotNull(builder.metaData["deterministic"]) - for (edge in ArrayList(builder.getEdges())) { - val edges = edge.splitIf(this::predicate) - if (edges.size > 1 || (edges.size == 1 && predicate( - (edges[0].label as SequenceLabel).labels[0]))) { - builder.removeEdge(edge) - edges.forEach { - if (predicate((it.label as SequenceLabel).labels[0])) { - builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel(listOf(NopLabel)), it.metadata)) - } else { - builder.addEdge(it) - } - } - } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + checkNotNull(builder.metaData["deterministic"]) + for (edge in ArrayList(builder.getEdges())) { + val edges = edge.splitIf(this::predicate) + if ( + edges.size > 1 || + (edges.size == 1 && predicate((edges[0].label as SequenceLabel).labels[0])) + ) { + builder.removeEdge(edge) + edges.forEach { + if (predicate((it.label as SequenceLabel).labels[0])) { + builder.addEdge( + XcfaEdge(it.source, it.target, SequenceLabel(listOf(NopLabel)), it.metadata) + ) + } else { + builder.addEdge(it) + } } - return builder + } } + return builder + } - private fun predicate(label: XcfaLabel): Boolean { - return label is InvokeLabel && listOf( - Regex("sleep"), - Regex("free"), - Regex("pthread_mutex_destroy"), // TODO: is this safe? - ).any { label.name.matches(it) } - } -} \ No newline at end of file + private fun predicate(label: XcfaLabel): Boolean { + return label is InvokeLabel && + listOf( + Regex("sleep"), + Regex("free"), + Regex("pthread_mutex_destroy"), // TODO: is this safe? + ) + .any { label.name.matches(it) } + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt index 9c2819461c..3e5167823a 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/NondetFunctionPass.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.core.decl.VarDecl @@ -21,36 +20,40 @@ import hu.bme.mit.theta.core.stmt.HavocStmt import hu.bme.mit.theta.core.type.anytype.RefExpr import hu.bme.mit.theta.xcfa.model.* -/** - * Transforms all procedure calls into havocs. - * Requires the ProcedureBuilder be `deterministic`. - */ +/** Transforms all procedure calls into havocs. Requires the ProcedureBuilder be `deterministic`. */ class NondetFunctionPass : ProcedurePass { - override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { - checkNotNull(builder.metaData["deterministic"]) - for (edge in ArrayList(builder.getEdges())) { - val edges = edge.splitIf(this::predicate) - if (edges.size > 1 || (edges.size == 1 && predicate( - (edges[0].label as SequenceLabel).labels[0]))) { - builder.removeEdge(edge) - edges.forEach { - if (predicate((it.label as SequenceLabel).labels[0])) { - val invokeLabel = it.label.labels[0] as InvokeLabel - val havoc = HavocStmt.of( - (invokeLabel.params[0] as RefExpr<*>).decl as VarDecl<*>) - builder.addEdge(XcfaEdge(it.source, it.target, SequenceLabel( - listOf(StmtLabel(havoc, metadata = invokeLabel.metadata))), it.metadata)) - } else { - builder.addEdge(it) - } - } - } + override fun run(builder: XcfaProcedureBuilder): XcfaProcedureBuilder { + checkNotNull(builder.metaData["deterministic"]) + for (edge in ArrayList(builder.getEdges())) { + val edges = edge.splitIf(this::predicate) + if ( + edges.size > 1 || + (edges.size == 1 && predicate((edges[0].label as SequenceLabel).labels[0])) + ) { + builder.removeEdge(edge) + edges.forEach { + if (predicate((it.label as SequenceLabel).labels[0])) { + val invokeLabel = it.label.labels[0] as InvokeLabel + val havoc = HavocStmt.of((invokeLabel.params[0] as RefExpr<*>).decl as VarDecl<*>) + builder.addEdge( + XcfaEdge( + it.source, + it.target, + SequenceLabel(listOf(StmtLabel(havoc, metadata = invokeLabel.metadata))), + it.metadata, + ) + ) + } else { + builder.addEdge(it) + } } - return builder + } } + return builder + } - private fun predicate(it: XcfaLabel): Boolean { - return it is InvokeLabel && it.name.startsWith("__VERIFIER_nondet") - } -} \ No newline at end of file + private fun predicate(it: XcfaLabel): Boolean { + return it is InvokeLabel && it.name.startsWith("__VERIFIER_nondet") + } +} diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt index 43594c362a..6c00d3f8f2 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/passes/Utils.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.passes import hu.bme.mit.theta.core.decl.Decl @@ -30,137 +29,162 @@ import hu.bme.mit.theta.xcfa.getFlatLabels import hu.bme.mit.theta.xcfa.model.* import java.util.* -/** - * XcfaEdge must be in a `deterministic` ProcedureBuilder - */ +/** XcfaEdge must be in a `deterministic` ProcedureBuilder */ fun XcfaEdge.splitIf(function: (XcfaLabel) -> Boolean): List { - check(label is SequenceLabel) - val newLabels = ArrayList() - var current = ArrayList() - for (label in label.labels) { - if (function(label)) { - if (current.size > 0) { - newLabels.add(SequenceLabel(current)) - current = ArrayList() - } - newLabels.add(SequenceLabel(listOf(label))) - } else { - current.add(label) - } + check(label is SequenceLabel) + val newLabels = ArrayList() + var current = ArrayList() + for (label in label.labels) { + if (function(label)) { + if (current.size > 0) { + newLabels.add(SequenceLabel(current)) + current = ArrayList() + } + newLabels.add(SequenceLabel(listOf(label))) + } else { + current.add(label) } - if (current.size > 0) newLabels.add(SequenceLabel(current)) - - val locations = ArrayList() - locations.add(source) - for (i in 2..(newLabels.size)) { - locations.add(XcfaLocation("loc" + XcfaLocation.uniqueCounter(), metadata = EmptyMetaData)) - } - locations.add(target) - - val newEdges = ArrayList() - for ((i, label) in newLabels.withIndex()) { - newEdges.add(XcfaEdge(locations[i], locations[i + 1], label, metadata)) - } - return newEdges + } + if (current.size > 0) newLabels.add(SequenceLabel(current)) + + val locations = ArrayList() + locations.add(source) + for (i in 2..(newLabels.size)) { + locations.add(XcfaLocation("loc" + XcfaLocation.uniqueCounter(), metadata = EmptyMetaData)) + } + locations.add(target) + + val newEdges = ArrayList() + for ((i, label) in newLabels.withIndex()) { + newEdges.add(XcfaEdge(locations[i], locations[i + 1], label, metadata)) + } + return newEdges } fun Stmt.flatten(): List { - return when (this) { - is SequenceStmt -> stmts.map { it.flatten() }.flatten() - is NonDetStmt -> error("Not possible") - else -> listOf(this) - } + return when (this) { + is SequenceStmt -> stmts.map { it.flatten() }.flatten() + is NonDetStmt -> error("Not possible") + else -> listOf(this) + } } @JvmOverloads -fun XcfaLabel.changeVars(varLut: Map, VarDecl<*>>, parseContext: ParseContext? = null): XcfaLabel = - if (varLut.isNotEmpty()) - when (this) { - is InvokeLabel -> InvokeLabel(name, params.map { it.changeVars(varLut, parseContext) }, - metadata = metadata) - - is JoinLabel -> JoinLabel(pidVar.changeVars(varLut), metadata = metadata) - is NondetLabel -> NondetLabel(labels.map { it.changeVars(varLut, parseContext) }.toSet(), - metadata = metadata) - - is ReadLabel -> ReadLabel(local.changeVars(varLut), global.changeVars(varLut), labels, - metadata = metadata) - - is SequenceLabel -> SequenceLabel(labels.map { it.changeVars(varLut, parseContext) }, - metadata = metadata) - - is StartLabel -> StartLabel(name, params.map { it.changeVars(varLut, parseContext) }, - pidVar.changeVars(varLut), metadata = metadata) - - is StmtLabel -> StmtLabel(stmt.changeVars(varLut, parseContext), metadata = metadata, - choiceType = this.choiceType) - - is WriteLabel -> WriteLabel(local.changeVars(varLut), global.changeVars(varLut), labels, - metadata = metadata) - - is ReturnLabel -> ReturnLabel(enclosedLabel.changeVars(varLut)) - - else -> this - } - else this +fun XcfaLabel.changeVars( + varLut: Map, VarDecl<*>>, + parseContext: ParseContext? = null, +): XcfaLabel = + if (varLut.isNotEmpty()) + when (this) { + is InvokeLabel -> + InvokeLabel(name, params.map { it.changeVars(varLut, parseContext) }, metadata = metadata) + + is JoinLabel -> JoinLabel(pidVar.changeVars(varLut), metadata = metadata) + is NondetLabel -> + NondetLabel(labels.map { it.changeVars(varLut, parseContext) }.toSet(), metadata = metadata) + + is ReadLabel -> + ReadLabel(local.changeVars(varLut), global.changeVars(varLut), labels, metadata = metadata) + + is SequenceLabel -> + SequenceLabel(labels.map { it.changeVars(varLut, parseContext) }, metadata = metadata) + + is StartLabel -> + StartLabel( + name, + params.map { it.changeVars(varLut, parseContext) }, + pidVar.changeVars(varLut), + metadata = metadata, + ) + + is StmtLabel -> + StmtLabel( + stmt.changeVars(varLut, parseContext), + metadata = metadata, + choiceType = this.choiceType, + ) + + is WriteLabel -> + WriteLabel(local.changeVars(varLut), global.changeVars(varLut), labels, metadata = metadata) + + is ReturnLabel -> ReturnLabel(enclosedLabel.changeVars(varLut)) + + else -> this + } + else this @JvmOverloads -fun Stmt.changeVars(varLut: Map, VarDecl<*>>, parseContext: ParseContext? = null): Stmt { - val stmt = when (this) { - is AssignStmt<*> -> AssignStmt.of(cast(varDecl.changeVars(varLut), varDecl.type), - cast(expr.changeVars(varLut, parseContext), varDecl.type)) - - is MemoryAssignStmt<*, *, *> -> MemoryAssignStmt.create(deref.changeVars(varLut) as Dereference, - expr.changeVars(varLut)) - - is HavocStmt<*> -> HavocStmt.of(varDecl.changeVars(varLut)) - is AssumeStmt -> AssumeStmt.of(cond.changeVars(varLut, parseContext)) - is SequenceStmt -> SequenceStmt.of(stmts.map { it.changeVars(varLut, parseContext) }) - is SkipStmt -> this - else -> TODO("Not yet implemented") +fun Stmt.changeVars( + varLut: Map, VarDecl<*>>, + parseContext: ParseContext? = null, +): Stmt { + val stmt = + when (this) { + is AssignStmt<*> -> + AssignStmt.of( + cast(varDecl.changeVars(varLut), varDecl.type), + cast(expr.changeVars(varLut, parseContext), varDecl.type), + ) + + is MemoryAssignStmt<*, *, *> -> + MemoryAssignStmt.create( + deref.changeVars(varLut) as Dereference, + expr.changeVars(varLut), + ) + + is HavocStmt<*> -> HavocStmt.of(varDecl.changeVars(varLut)) + is AssumeStmt -> AssumeStmt.of(cond.changeVars(varLut, parseContext)) + is SequenceStmt -> SequenceStmt.of(stmts.map { it.changeVars(varLut, parseContext) }) + is SkipStmt -> this + else -> TODO("Not yet implemented") } - val metadataValue = parseContext?.getMetadata()?.getMetadataValue(this, "sourceStatement") - if (metadataValue?.isPresent == true) - parseContext.getMetadata().create(stmt, "sourceStatement", metadataValue.get()) - return stmt + val metadataValue = parseContext?.getMetadata()?.getMetadataValue(this, "sourceStatement") + if (metadataValue?.isPresent == true) + parseContext.getMetadata().create(stmt, "sourceStatement", metadataValue.get()) + return stmt } @JvmOverloads -fun Expr.changeVars(varLut: Map, VarDecl<*>>, parseContext: ParseContext? = null): Expr = - if (this is RefExpr) (decl as Decl).changeVars(varLut).ref - else { - val ret = this.withOps(this.ops.map { it.changeVars(varLut, parseContext) }) - if (parseContext?.metadata?.getMetadataValue(this, "cType")?.isPresent == true) { - parseContext.metadata?.create(ret, "cType", CComplexType.getType(this, parseContext)) - } - ret +fun Expr.changeVars( + varLut: Map, VarDecl<*>>, + parseContext: ParseContext? = null, +): Expr = + if (this is RefExpr) (decl as Decl).changeVars(varLut).ref + else { + val ret = this.withOps(this.ops.map { it.changeVars(varLut, parseContext) }) + if (parseContext?.metadata?.getMetadataValue(this, "cType")?.isPresent == true) { + parseContext.metadata?.create(ret, "cType", CComplexType.getType(this, parseContext)) } + ret + } fun Decl.changeVars(varLut: Map, VarDecl<*>>): Decl = - (varLut[this] as? Decl ?: this) + (varLut[this] as? Decl ?: this) fun VarDecl.changeVars(varLut: Map, VarDecl<*>>): VarDecl = - (varLut[this] ?: this) as VarDecl - + (varLut[this] ?: this) as VarDecl fun XcfaProcedureBuilder.canInline(): Boolean = canInline(LinkedList()) + private fun XcfaProcedureBuilder.canInline(tally: LinkedList): Boolean { - if (metaData["recursive"] != null) return false - if (metaData["canInline"] != null) return true - - tally.push(name) - val recursive = getEdges() - .asSequence() - .map { it.getFlatLabels() }.flatten() - .filterIsInstance() - .mapNotNull { parent.getProcedures().find { proc -> proc.name == it.name } } - .any { tally.contains(it.name) || !it.canInline(tally) } - tally.pop() - metaData[if (recursive) "recursive" else "canInline"] = Unit - return !recursive + if (metaData["recursive"] != null) return false + if (metaData["canInline"] != null) return true + + tally.push(name) + val recursive = + getEdges() + .asSequence() + .map { it.getFlatLabels() } + .flatten() + .filterIsInstance() + .mapNotNull { parent.getProcedures().find { proc -> proc.name == it.name } } + .any { tally.contains(it.name) || !it.canInline(tally) } + tally.pop() + metaData[if (recursive) "recursive" else "canInline"] = Unit + return !recursive } fun combineMetadata(vararg metaData: MetaData): MetaData = combineMetadata(metaData.toList()) fun combineMetadata(metaData: Collection): MetaData = - metaData.reduce { i1, i2 -> i1.combine(i2) } + metaData.reduce { i1, i2 -> i1.combine(i2) } diff --git a/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt b/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt index 456f2e4703..161f8a4f1a 100644 --- a/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt +++ b/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt @@ -37,83 +37,89 @@ import hu.bme.mit.theta.grammar.gson.StringTypeAdapter import hu.bme.mit.theta.grammar.gson.VarDeclAdapter import hu.bme.mit.theta.xcfa.XcfaScope import hu.bme.mit.theta.xcfa.model.* +import java.util.* import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import java.util.* class GsonTest { - private fun getGson(scope: XcfaScope, env: Env, newScope: Boolean): Gson { - val gsonBuilder = GsonBuilder() - lateinit var gson: Gson - gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, XcfaLocationAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(XCFA::class.java, XcfaAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(VarDecl::class.java, - VarDeclAdapter({ gson }, scope, env, !newScope)) - gsonBuilder.registerTypeHierarchyAdapter(Stmt::class.java, - StringTypeAdapter { StatementWrapper(it, scope).instantiate(env) }) - gsonBuilder.registerTypeHierarchyAdapter(Expr::class.java, - StringTypeAdapter { ExpressionWrapper(scope, it).instantiate(env) }) - gsonBuilder.registerTypeHierarchyAdapter(Type::class.java, - StringTypeAdapter { TypeWrapper(it).instantiate() }) - gsonBuilder.registerTypeHierarchyAdapter(VarIndexing::class.java, - StringTypeAdapter { BasicVarIndexing.fromString(it, scope, env) }) - gsonBuilder.registerTypeHierarchyAdapter(XcfaLabel::class.java, - XcfaLabelAdapter(scope, env, { gson })) - gsonBuilder.registerTypeHierarchyAdapter(MetaData::class.java, MetaDataAdapter()) - gsonBuilder.registerTypeHierarchyAdapter(Pair::class.java, PairAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(Optional::class.java, OptionalAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(ParseContext::class.java, - ParseContextAdapter { gson }) - gsonBuilder.registerTypeHierarchyAdapter(FrontendMetadata::class.java, - FrontendMetadataAdapter { gson }) - gson = gsonBuilder.create() - return gson - } - - @Test - fun testRoundtrip() { - val xcfaSource = xcfa("example") { - global { "x" type Int() init "0" } - procedure("main") { - (init to final) { - "proc1"("x") - } - } - procedure("proc1") { - (init to final) { - assume("true") - } - } - } - - val symbolTable = XcfaScope(SymbolTable()) - val x_symbol = NamedSymbol("x") - symbolTable.add(x_symbol) - val env = Env() - env.define(x_symbol, xcfaSource.vars.find { it.wrappedVar.name == "x" }!!.wrappedVar) - val gson = getGson(symbolTable, env, true) + private fun getGson(scope: XcfaScope, env: Env, newScope: Boolean): Gson { + val gsonBuilder = GsonBuilder() + lateinit var gson: Gson + gsonBuilder.registerTypeHierarchyAdapter(XcfaLocation::class.java, XcfaLocationAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter(XCFA::class.java, XcfaAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter( + VarDecl::class.java, + VarDeclAdapter({ gson }, scope, env, !newScope), + ) + gsonBuilder.registerTypeHierarchyAdapter( + Stmt::class.java, + StringTypeAdapter { StatementWrapper(it, scope).instantiate(env) }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + Expr::class.java, + StringTypeAdapter { ExpressionWrapper(scope, it).instantiate(env) }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + Type::class.java, + StringTypeAdapter { TypeWrapper(it).instantiate() }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + VarIndexing::class.java, + StringTypeAdapter { BasicVarIndexing.fromString(it, scope, env) }, + ) + gsonBuilder.registerTypeHierarchyAdapter( + XcfaLabel::class.java, + XcfaLabelAdapter(scope, env, { gson }), + ) + gsonBuilder.registerTypeHierarchyAdapter(MetaData::class.java, MetaDataAdapter()) + gsonBuilder.registerTypeHierarchyAdapter(Pair::class.java, PairAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter(Optional::class.java, OptionalAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter(ParseContext::class.java, ParseContextAdapter { gson }) + gsonBuilder.registerTypeHierarchyAdapter( + FrontendMetadata::class.java, + FrontendMetadataAdapter { gson }, + ) + gson = gsonBuilder.create() + return gson + } - val output = gson.fromJson(gson.toJson(xcfaSource), XCFA::class.java) - println(xcfaSource) - println(output) - assertEquals(xcfaSource, output) - } + @Test + fun testRoundtrip() { + val xcfaSource = + xcfa("example") { + global { "x" type Int() init "0" } + procedure("main") { (init to final) { "proc1"("x") } } + procedure("proc1") { (init to final) { assume("true") } } + } - @Test - fun testParseContextRoundTrip() { - val parseContext = ParseContext() - parseContext.metadata.create("owner", "key", "value") + val symbolTable = XcfaScope(SymbolTable()) + val x_symbol = NamedSymbol("x") + symbolTable.add(x_symbol) + val env = Env() + env.define(x_symbol, xcfaSource.vars.find { it.wrappedVar.name == "x" }!!.wrappedVar) + val gson = getGson(symbolTable, env, true) - val symbolTable = XcfaScope(SymbolTable()) - val x_symbol = NamedSymbol("x") - symbolTable.add(x_symbol) - val env = Env() + val output = gson.fromJson(gson.toJson(xcfaSource), XCFA::class.java) + println(xcfaSource) + println(output) + assertEquals(xcfaSource, output) + } - val gson = getGson(symbolTable, env, true) - assertEquals(parseContext.metadata.lookupKeyValue, - gson.fromJson(gson.toJson(parseContext), ParseContext::class.java).metadata.lookupKeyValue) + @Test + fun testParseContextRoundTrip() { + val parseContext = ParseContext() + parseContext.metadata.create("owner", "key", "value") - } + val symbolTable = XcfaScope(SymbolTable()) + val x_symbol = NamedSymbol("x") + symbolTable.add(x_symbol) + val env = Env() -} \ No newline at end of file + val gson = getGson(symbolTable, env, true) + assertEquals( + parseContext.metadata.lookupKeyValue, + gson.fromJson(gson.toJson(parseContext), ParseContext::class.java).metadata.lookupKeyValue, + ) + } +} diff --git a/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java b/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java index 7a3a159a80..52ae4fa72d 100644 --- a/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java +++ b/subprojects/xsts/xsts-analysis/src/test/java/hu/bme/mit/theta/xsts/analysis/XstsHornTest.java @@ -15,6 +15,8 @@ */ package hu.bme.mit.theta.xsts.analysis; +import static org.junit.Assert.assertTrue; + import hu.bme.mit.theta.analysis.algorithm.SafetyResult; import hu.bme.mit.theta.analysis.algorithm.chc.HornChecker; import hu.bme.mit.theta.common.OsHelper; @@ -28,20 +30,17 @@ import hu.bme.mit.theta.xsts.XSTS; import hu.bme.mit.theta.xsts.analysis.util.ChcUtilsKt; import hu.bme.mit.theta.xsts.dsl.XstsDslManager; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - import java.io.FileInputStream; import java.io.InputStream; import java.io.SequenceInputStream; import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; - -import static org.junit.Assert.assertTrue; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; @RunWith(value = Parameterized.class) public class XstsHornTest { @@ -62,294 +61,479 @@ public class XstsHornTest { @Parameterized.Parameters(name = "{index}: {0}, {1}, {2}, {3}") public static Collection data() { - return Arrays.asList(new Object[][]{ - - {"src/test/resources/model/trafficlight.xsts", - "src/test/resources/property/green_and_red.prop", true, - "z3:4.13.0"}, - - {"src/test/resources/model/trafficlight.xsts", - "src/test/resources/property/green_and_red.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/trafficlight.xsts", - "src/test/resources/property/green_and_red.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/trafficlight_v2.xsts", - "src/test/resources/property/green_and_red.prop", true, - "z3:4.13.0"}, - -// {"src/test/resources/model/trafficlight_v2.xsts", -// "src/test/resources/property/green_and_red.prop", true, -// "eldarica:2.1"}, - - {"src/test/resources/model/trafficlight_v2.xsts", - "src/test/resources/property/green_and_red.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/counter5.xsts", - "src/test/resources/property/x_between_0_and_5.prop", true, - "z3:4.13.0"}, - - {"src/test/resources/model/counter5.xsts", - "src/test/resources/property/x_between_0_and_5.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/counter5.xsts", - "src/test/resources/property/x_between_0_and_5.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/counter5.xsts", "src/test/resources/property/x_eq_5.prop", - false, "z3:4.13.0"}, - - {"src/test/resources/model/counter5.xsts", "src/test/resources/property/x_eq_5.prop", - false, "eldarica:2.1"}, - - {"src/test/resources/model/counter5.xsts", "src/test/resources/property/x_eq_5.prop", - false, "golem:0.5.0"}, - - {"src/test/resources/model/x_and_y.xsts", "src/test/resources/property/x_geq_y.prop", - true, "eldarica:2.1"}, - - {"src/test/resources/model/x_powers.xsts", "src/test/resources/property/x_even.prop", - true, "eldarica:2.1"}, - -// {"src/test/resources/model/cross_with.xsts", "src/test/resources/property/cross.prop", -// false, "eldarica:2.1"}, - -// { "src/test/resources/model/cross_with.xsts", "src/test/resources/property/cross.prop", false, "z3:4.13.0"}, - -// { "src/test/resources/model/cross_with.xsts", "src/test/resources/property/cross.prop", false, XstsConfigBuilder.Domain.PROD}, -// -// {"src/test/resources/model/cross_without.xsts", -// "src/test/resources/property/cross.prop", false, -// "eldarica:2.1"}, - -// { "src/test/resources/model/cross_without.xsts", "src/test/resources/property/cross.prop", false, "z3:4.13.0"}, - -// { "src/test/resources/model/cross_without.xsts", "src/test/resources/property/cross.prop", false, XstsConfigBuilder.Domain.PROD}, - - {"src/test/resources/model/choices.xsts", "src/test/resources/property/choices.prop", - false, "eldarica:2.1"}, - - {"src/test/resources/model/choices.xsts", "src/test/resources/property/choices.prop", - false, "z3:4.13.0"}, - - {"src/test/resources/model/choices.xsts", "src/test/resources/property/choices.prop", - false, "golem:0.5.0"}, - - {"src/test/resources/model/literals.xsts", "src/test/resources/property/literals.prop", - false, "eldarica:2.1"}, - - {"src/test/resources/model/literals.xsts", "src/test/resources/property/literals.prop", - false, "z3:4.13.0"}, - - {"src/test/resources/model/literals.xsts", "src/test/resources/property/literals.prop", - false, "golem:0.5.0"}, - -// {"src/test/resources/model/cross3.xsts", "src/test/resources/property/cross.prop", -// false, "eldarica:2.1"}, - -// { "src/test/resources/model/cross3.xsts", "src/test/resources/property/cross.prop", false, "z3:4.13.0"}, - -// { "src/test/resources/model/cross3.xsts", "src/test/resources/property/cross.prop", false, XstsConfigBuilder.Domain.PROD}, - - {"src/test/resources/model/sequential.xsts", - "src/test/resources/property/sequential.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/sequential.xsts", - "src/test/resources/property/sequential.prop", true, "z3:4.13.0"}, - - {"src/test/resources/model/sequential.xsts", - "src/test/resources/property/sequential.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/sequential.xsts", - "src/test/resources/property/sequential2.prop", false, - "eldarica:2.1"}, - - {"src/test/resources/model/sequential.xsts", - "src/test/resources/property/sequential2.prop", false, - "z3:4.13.0"}, - - {"src/test/resources/model/sequential.xsts", - "src/test/resources/property/sequential2.prop", false, - "golem:0.5.0"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine.prop", false, - "eldarica:2.1"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine.prop", false, - "z3:4.13.0"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine.prop", false, - "golem:0.5.0"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine2.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine2.prop", true, - "z3:4.13.0"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine2.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine3.prop", false, - "eldarica:2.1"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine3.prop", false, - "z3:4.13.0"}, - - {"src/test/resources/model/on_off_statemachine.xsts", - "src/test/resources/property/on_off_statemachine3.prop", false, - "golem:0.5.0"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_5.prop", - false, "eldarica:2.1"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_5.prop", - false, "z3:4.13.0"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_5.prop", - false, "golem:0.5.0"}, - -// { "src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_50.prop", false, "eldarica:2.1"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_50.prop", - false, "z3:4.13.0"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_50.prop", - false, "golem:0.5.0"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_51.prop", - true, "eldarica:2.1"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_51.prop", - true, "z3:4.13.0"}, - - {"src/test/resources/model/counter50.xsts", "src/test/resources/property/x_eq_51.prop", - true, "golem:0.5.0"}, -// -// {"src/test/resources/model/count_up_down.xsts", -// "src/test/resources/property/count_up_down.prop", false, -// "eldarica:2.1"}, - - {"src/test/resources/model/count_up_down.xsts", - "src/test/resources/property/count_up_down.prop", false, - "z3:4.13.0"}, - - {"src/test/resources/model/count_up_down.xsts", - "src/test/resources/property/count_up_down.prop", false, - "golem:0.5.0"}, - - {"src/test/resources/model/count_up_down.xsts", - "src/test/resources/property/count_up_down2.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/count_up_down.xsts", - "src/test/resources/property/count_up_down2.prop", true, - "z3:4.13.0"}, - - {"src/test/resources/model/count_up_down.xsts", - "src/test/resources/property/count_up_down2.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/bhmr2007.xsts", "src/test/resources/property/bhmr2007.prop", - true, "eldarica:2.1"}, - -// { "src/test/resources/model/bhmr2007.xsts", "src/test/resources/property/bhmr2007.prop", true, "z3:4.13.0"}, - -// { "src/test/resources/model/bhmr2007.xsts", "src/test/resources/property/bhmr2007.prop", true, XstsConfigBuilder.Domain.PROD}, - - {"src/test/resources/model/css2003.xsts", "src/test/resources/property/css2003.prop", - true, "eldarica:2.1"}, - - {"src/test/resources/model/css2003.xsts", "src/test/resources/property/css2003.prop", - true, "z3:4.13.0"}, - - {"src/test/resources/model/css2003.xsts", "src/test/resources/property/css2003.prop", - true, "golem:0.5.0"}, - -// { "src/test/resources/model/ort.xsts", "src/test/resources/property/x_gt_2.prop", false, "eldarica:2.1"}, - -// { "src/test/resources/model/ort2.xsts", "src/test/resources/property/ort2.prop", true, "eldarica:2.1"}, - -// { "src/test/resources/model/crossroad_composite.xsts", "src/test/resources/property/both_green.prop", true, "z3:4.13.0"} - -// {"src/test/resources/model/array_counter.xsts", -// "src/test/resources/property/array_10.prop", false, -// "eldarica:2.1"}, - - {"src/test/resources/model/array_counter.xsts", - "src/test/resources/property/array_10.prop", false, "z3:4.13.0"}, -// -// {"src/test/resources/model/array_counter.xsts", -// "src/test/resources/property/array_10.prop", false, -// "golem:0.5.0"}, -// -// {"src/test/resources/model/array_constant.xsts", -// "src/test/resources/property/array_constant.prop", true, -// "eldarica:2.1"}, - - {"src/test/resources/model/array_constant.xsts", - "src/test/resources/property/array_constant.prop", true, - "z3:4.13.0"}, -// -// {"src/test/resources/model/array_constant.xsts", -// "src/test/resources/property/array_constant.prop", true, -// "golem:0.5.0"}, - - {"src/test/resources/model/localvars.xsts", - "src/test/resources/property/localvars.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/localvars.xsts", - "src/test/resources/property/localvars.prop", true, "z3:4.13.0"}, - - {"src/test/resources/model/localvars.xsts", - "src/test/resources/property/localvars.prop", true, - "golem:0.5.0"}, - - {"src/test/resources/model/localvars2.xsts", - "src/test/resources/property/localvars2.prop", true, - "eldarica:2.1"}, - - {"src/test/resources/model/localvars2.xsts", - "src/test/resources/property/localvars2.prop", true, "z3:4.13.0"}, - - {"src/test/resources/model/localvars2.xsts", - "src/test/resources/property/localvars2.prop", true, - "golem:0.5.0"}, - -// {"src/test/resources/model/loopxy.xsts", "src/test/resources/property/loopxy.prop", -// true, "z3:4.13.0"}, -// -// {"src/test/resources/model/loopxy.xsts", "src/test/resources/property/loopxy.prop", -// true, "golem:0.5.0"}, -// -// {"src/test/resources/model/loopxy.xsts", "src/test/resources/property/loopxy.prop", -// true, "eldarica:2.1"}, - - {"src/test/resources/model/arraywrite_sugar.xsts", - "src/test/resources/property/arraywrite_sugar.prop", false, - "eldarica:2.1"}, -// -// {"src/test/resources/model/if1.xsts", "src/test/resources/property/if1.prop", true, -// "eldarica:2.1"}, - -// {"src/test/resources/model/if2.xsts", "src/test/resources/property/if2.prop", false, -// "golem:0.5.0"} - }); + return Arrays.asList( + new Object[][] { + { + "src/test/resources/model/trafficlight.xsts", + "src/test/resources/property/green_and_red.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/trafficlight.xsts", + "src/test/resources/property/green_and_red.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/trafficlight.xsts", + "src/test/resources/property/green_and_red.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/trafficlight_v2.xsts", + "src/test/resources/property/green_and_red.prop", + true, + "z3:4.13.0" + }, + + // {"src/test/resources/model/trafficlight_v2.xsts", + // "src/test/resources/property/green_and_red.prop", + // true, + // "eldarica:2.1"}, + + { + "src/test/resources/model/trafficlight_v2.xsts", + "src/test/resources/property/green_and_red.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_between_0_and_5.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_between_0_and_5.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_between_0_and_5.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_eq_5.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_eq_5.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/counter5.xsts", + "src/test/resources/property/x_eq_5.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/x_and_y.xsts", + "src/test/resources/property/x_geq_y.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/x_powers.xsts", + "src/test/resources/property/x_even.prop", + true, + "eldarica:2.1" + }, + + // {"src/test/resources/model/cross_with.xsts", + // "src/test/resources/property/cross.prop", + // false, "eldarica:2.1"}, + + // { "src/test/resources/model/cross_with.xsts", + // "src/test/resources/property/cross.prop", false, "z3:4.13.0"}, + + // { "src/test/resources/model/cross_with.xsts", + // "src/test/resources/property/cross.prop", false, + // XstsConfigBuilder.Domain.PROD}, + // + // {"src/test/resources/model/cross_without.xsts", + // "src/test/resources/property/cross.prop", false, + // "eldarica:2.1"}, + + // { "src/test/resources/model/cross_without.xsts", + // "src/test/resources/property/cross.prop", false, "z3:4.13.0"}, + + // { "src/test/resources/model/cross_without.xsts", + // "src/test/resources/property/cross.prop", false, + // XstsConfigBuilder.Domain.PROD}, + + { + "src/test/resources/model/choices.xsts", + "src/test/resources/property/choices.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/choices.xsts", + "src/test/resources/property/choices.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/choices.xsts", + "src/test/resources/property/choices.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/literals.xsts", + "src/test/resources/property/literals.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/literals.xsts", + "src/test/resources/property/literals.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/literals.xsts", + "src/test/resources/property/literals.prop", + false, + "golem:0.5.0" + }, + + // {"src/test/resources/model/cross3.xsts", + // "src/test/resources/property/cross.prop", + // false, "eldarica:2.1"}, + + // { "src/test/resources/model/cross3.xsts", + // "src/test/resources/property/cross.prop", false, "z3:4.13.0"}, + + // { "src/test/resources/model/cross3.xsts", + // "src/test/resources/property/cross.prop", false, + // XstsConfigBuilder.Domain.PROD}, + + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential2.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential2.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/sequential.xsts", + "src/test/resources/property/sequential2.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine2.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine2.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine2.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine3.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine3.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/on_off_statemachine.xsts", + "src/test/resources/property/on_off_statemachine3.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_5.prop", + false, + "eldarica:2.1" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_5.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_5.prop", + false, + "golem:0.5.0" + }, + + // { "src/test/resources/model/counter50.xsts", + // "src/test/resources/property/x_eq_50.prop", false, "eldarica:2.1"}, + + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_50.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_50.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_51.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_51.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/counter50.xsts", + "src/test/resources/property/x_eq_51.prop", + true, + "golem:0.5.0" + }, + // + // {"src/test/resources/model/count_up_down.xsts", + // "src/test/resources/property/count_up_down.prop", + // false, + // "eldarica:2.1"}, + + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down.prop", + false, + "z3:4.13.0" + }, + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down.prop", + false, + "golem:0.5.0" + }, + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down2.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down2.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/count_up_down.xsts", + "src/test/resources/property/count_up_down2.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/bhmr2007.xsts", + "src/test/resources/property/bhmr2007.prop", + true, + "eldarica:2.1" + }, + + // { "src/test/resources/model/bhmr2007.xsts", + // "src/test/resources/property/bhmr2007.prop", true, "z3:4.13.0"}, + + // { "src/test/resources/model/bhmr2007.xsts", + // "src/test/resources/property/bhmr2007.prop", true, + // XstsConfigBuilder.Domain.PROD}, + + { + "src/test/resources/model/css2003.xsts", + "src/test/resources/property/css2003.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/css2003.xsts", + "src/test/resources/property/css2003.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/css2003.xsts", + "src/test/resources/property/css2003.prop", + true, + "golem:0.5.0" + }, + + // { "src/test/resources/model/ort.xsts", + // "src/test/resources/property/x_gt_2.prop", false, "eldarica:2.1"}, + + // { "src/test/resources/model/ort2.xsts", + // "src/test/resources/property/ort2.prop", true, "eldarica:2.1"}, + + // { "src/test/resources/model/crossroad_composite.xsts", + // "src/test/resources/property/both_green.prop", true, "z3:4.13.0"} + + // {"src/test/resources/model/array_counter.xsts", + // "src/test/resources/property/array_10.prop", false, + // "eldarica:2.1"}, + + { + "src/test/resources/model/array_counter.xsts", + "src/test/resources/property/array_10.prop", + false, + "z3:4.13.0" + }, + // + // {"src/test/resources/model/array_counter.xsts", + // "src/test/resources/property/array_10.prop", false, + // "golem:0.5.0"}, + // + // {"src/test/resources/model/array_constant.xsts", + // "src/test/resources/property/array_constant.prop", + // true, + // "eldarica:2.1"}, + + { + "src/test/resources/model/array_constant.xsts", + "src/test/resources/property/array_constant.prop", + true, + "z3:4.13.0" + }, + // + // {"src/test/resources/model/array_constant.xsts", + // "src/test/resources/property/array_constant.prop", + // true, + // "golem:0.5.0"}, + + { + "src/test/resources/model/localvars.xsts", + "src/test/resources/property/localvars.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/localvars.xsts", + "src/test/resources/property/localvars.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/localvars.xsts", + "src/test/resources/property/localvars.prop", + true, + "golem:0.5.0" + }, + { + "src/test/resources/model/localvars2.xsts", + "src/test/resources/property/localvars2.prop", + true, + "eldarica:2.1" + }, + { + "src/test/resources/model/localvars2.xsts", + "src/test/resources/property/localvars2.prop", + true, + "z3:4.13.0" + }, + { + "src/test/resources/model/localvars2.xsts", + "src/test/resources/property/localvars2.prop", + true, + "golem:0.5.0" + }, + + // {"src/test/resources/model/loopxy.xsts", + // "src/test/resources/property/loopxy.prop", + // true, "z3:4.13.0"}, + // + // {"src/test/resources/model/loopxy.xsts", + // "src/test/resources/property/loopxy.prop", + // true, "golem:0.5.0"}, + // + // {"src/test/resources/model/loopxy.xsts", + // "src/test/resources/property/loopxy.prop", + // true, "eldarica:2.1"}, + + { + "src/test/resources/model/arraywrite_sugar.xsts", + "src/test/resources/property/arraywrite_sugar.prop", + false, + "eldarica:2.1" + }, + // + // {"src/test/resources/model/if1.xsts", + // "src/test/resources/property/if1.prop", true, + // "eldarica:2.1"}, + + // {"src/test/resources/model/if2.xsts", + // "src/test/resources/property/if2.prop", false, + // "golem:0.5.0"} + }); } @Before @@ -357,11 +541,20 @@ public void installSolver() { if (solverString.contains("Z3") || solverString.contains("JavaSMT")) { return; } - Assume.assumeTrue(OsHelper.getOs() == OsHelper.OperatingSystem.LINUX); // chc solvers are only properly on linux - try (final var solverManager = SmtLibSolverManager.create(SMTLIB_HOME, new ConsoleLogger(Level.DETAIL))) { + Assume.assumeTrue( + OsHelper.getOs() + == OsHelper.OperatingSystem + .LINUX); // chc solvers are only properly on linux + try (final var solverManager = + SmtLibSolverManager.create(SMTLIB_HOME, new ConsoleLogger(Level.DETAIL))) { String solverVersion = SmtLibSolverManager.getSolverVersion(solverString); String solverName = SmtLibSolverManager.getSolverName(solverString); - if (solverManager.managesSolver(solverString) && !solverManager.getInstalledVersions(solverName).contains(solverManager.getVersionString(solverName, solverVersion, false))) { + if (solverManager.managesSolver(solverString) + && !solverManager + .getInstalledVersions(solverName) + .contains( + solverManager.getVersionString( + solverName, solverVersion, false))) { solverManager.install(solverName, solverVersion, solverVersion, null, false); } } catch (Exception e) { @@ -372,7 +565,8 @@ public void installSolver() { @Test(timeout = 10_000) public void test() throws Exception { final Logger logger = new ConsoleLogger(Level.SUBSTEP); - SolverManager.registerSolverManager(hu.bme.mit.theta.solver.z3legacy.Z3SolverManager.create()); + SolverManager.registerSolverManager( + hu.bme.mit.theta.solver.z3legacy.Z3SolverManager.create()); SolverManager.registerSolverManager(hu.bme.mit.theta.solver.z3.Z3SolverManager.create()); SolverManager.registerSolverManager(SmtLibSolverManager.create(SMTLIB_HOME, logger)); SolverManager.registerSolverManager(JavaSMTSolverManager.create()); @@ -386,19 +580,16 @@ public void test() throws Exception { } XSTS xsts; - try (InputStream inputStream = new SequenceInputStream(new FileInputStream(filePath), - new FileInputStream(propPath))) { + try (InputStream inputStream = + new SequenceInputStream( + new FileInputStream(filePath), new FileInputStream(propPath))) { xsts = XstsDslManager.createXsts(inputStream); } try { final var relations = XstsToRelationsKt.toRelations(xsts); System.err.println(ChcUtilsKt.toSMT2(relations)); - final var checker = new HornChecker( - relations, - solverFactory, - logger - ); + final var checker = new HornChecker(relations, solverFactory, logger); final SafetyResult status = checker.check(); if (safe) { @@ -410,6 +601,4 @@ public void test() throws Exception { SolverManager.closeAll(); } } - } - From a49b95d7046046b8e798b9b0e980831fe9f39730 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:20:43 +0100 Subject: [PATCH 17/21] Formatted files From bda1f7275364776b329780ff50afbcc4ebbdd274 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:21:04 +0100 Subject: [PATCH 18/21] Formatted files From a6abad5e1bb16ee1118436bf66fdf6f00776cce4 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:24:00 +0100 Subject: [PATCH 19/21] version bump --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 06036a38d7..e4cbd21501 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,7 +29,7 @@ buildscript { allprojects { group = "hu.bme.mit.theta" - version = "6.6.4" + version = "6.6.5" apply(from = rootDir.resolve("gradle/shared-with-buildSrc/mirrors.gradle.kts")) } From 1ae278cd0a2ee82bc3c161b040ced1261d700315 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 22:58:16 +0100 Subject: [PATCH 20/21] fixed tests for windows --- .../java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt index bc39de1553..27c51fa5cf 100644 --- a/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt +++ b/subprojects/xcfa/xcfa-cli/src/test/java/hu/bme/mit/theta/xcfa/cli/XcfaCliProofTest.kt @@ -46,8 +46,8 @@ class XcfaCliProofTest { WitnessEdge( startlineRange = Pair(5, 5), endlineRange = Pair(5, 5), - startoffsetRange = Pair(80, 82), - endoffsetRange = Pair(112, 114), + startoffsetRange = Pair(80, 90), + endoffsetRange = Pair(112, 122), assumption = Regex("i *== *-1"), ) ), @@ -59,8 +59,8 @@ class XcfaCliProofTest { WitnessEdge( startlineRange = Pair(5, 5), endlineRange = Pair(5, 5), - startoffsetRange = Pair(80, 82), - endoffsetRange = Pair(112, 114), + startoffsetRange = Pair(80, 90), + endoffsetRange = Pair(112, 122), assumption = Regex("i *== *-1"), ) ), From 6fd2d6dea1ca7278a2fa52cc882a5692350ef7f1 Mon Sep 17 00:00:00 2001 From: Levente Bajczi Date: Sun, 3 Nov 2024 23:21:12 +0100 Subject: [PATCH 21/21] fixed parsing of labels --- .../hu/bme/mit/theta/xcfa/model/XcfaLabel.kt | 365 +++++++++--------- .../hu/bme/mit/theta/xcfa/gson/GsonTest.kt | 28 ++ 2 files changed, 216 insertions(+), 177 deletions(-) diff --git a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XcfaLabel.kt b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XcfaLabel.kt index 93f636b306..4e6a2251e0 100644 --- a/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XcfaLabel.kt +++ b/subprojects/xcfa/xcfa/src/main/java/hu/bme/mit/theta/xcfa/model/XcfaLabel.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package hu.bme.mit.theta.xcfa.model import hu.bme.mit.theta.common.dsl.Env @@ -30,242 +29,254 @@ import java.util.* sealed class XcfaLabel(open val metadata: MetaData) { - open fun toStmt(): Stmt = Skip() + open fun toStmt(): Stmt = Skip() } -data class InvokeLabel @JvmOverloads constructor( - val name: String, - val params: List>, - override val metadata: MetaData, - val tempLookup: Map, VarDecl<*>> = emptyMap() +data class InvokeLabel +@JvmOverloads +constructor( + val name: String, + val params: List>, + override val metadata: MetaData, + val tempLookup: Map, VarDecl<*>> = emptyMap(), ) : XcfaLabel(metadata) { - override fun toString(): String { - val sj = StringJoiner(", ", "(", ")") - params.forEach { sj.add(it.toString()) } - return "$name$sj" - } - - companion object { - - fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { - val (name, params) = Regex("([^\\(]*)\\((.*)\\)").matchEntire(s)!!.destructured - return InvokeLabel(name, - params.split(",").map { ExpressionWrapper(scope, it).instantiate(env) }, - metadata = metadata) - } + override fun toString(): String { + val sj = StringJoiner(", ", "(", ")") + params.forEach { sj.add(it.toString()) } + return "$name$sj" + } + + companion object { + + fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { + val (name, params) = Regex("^([^(]*)\\((.*)\\)$").matchEntire(s)!!.destructured + return InvokeLabel( + name, + params.split(",").map { ExpressionWrapper(scope, it).instantiate(env) }, + metadata = metadata, + ) } + } } data class ReturnLabel(val enclosedLabel: XcfaLabel) : - XcfaLabel(metadata = enclosedLabel.metadata) { + XcfaLabel(metadata = enclosedLabel.metadata) { - override fun toStmt(): Stmt { - return enclosedLabel.toStmt() - } + override fun toStmt(): Stmt { + return enclosedLabel.toStmt() + } - override fun toString(): String { - return "Return ($enclosedLabel)" - } + override fun toString(): String { + return "Return ($enclosedLabel)" + } } data class StartLabel( - val name: String, - val params: List>, - val pidVar: VarDecl<*>, - override val metadata: MetaData, - val tempLookup: Map, VarDecl<*>> = emptyMap() + val name: String, + val params: List>, + val pidVar: VarDecl<*>, + override val metadata: MetaData, + val tempLookup: Map, VarDecl<*>> = emptyMap(), ) : XcfaLabel(metadata = metadata) { - override fun toString(): String { - val sj = StringJoiner(", ", "(", ")") - params.forEach { sj.add(it.toString()) } - return "$pidVar = start $name$sj" - } - - companion object { - - fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { - val (pidVarName, pidVarType, name, params) = Regex( - "\\(var (.*) (.*)\\) = start (.*)\\((.*)\\)").matchEntire(s)!!.destructured - val pidVar = env.eval(scope.resolve(pidVarName).orElseThrow()) as VarDecl<*> - return StartLabel(name, - params.split(",").map { ExpressionWrapper(scope, it).instantiate(env) }, pidVar, - metadata = metadata) - } + override fun toString(): String { + val sj = StringJoiner(", ", "(", ")") + params.forEach { sj.add(it.toString()) } + return "$pidVar = start $name$sj" + } + + companion object { + + fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { + val (pidVarName, pidVarType, name, params) = + Regex("^\\(var (.*) (.*)\\) = start ([^(]*)\\((.*)\\)$").matchEntire(s)!!.destructured + val pidVar = env.eval(scope.resolve(pidVarName).orElseThrow()) as VarDecl<*> + return StartLabel( + name, + params.split(",").map { ExpressionWrapper(scope, it).instantiate(env) }, + pidVar, + metadata = metadata, + ) } + } } -data class JoinLabel( - val pidVar: VarDecl<*>, - override val metadata: MetaData -) : XcfaLabel(metadata = metadata) { +data class JoinLabel(val pidVar: VarDecl<*>, override val metadata: MetaData) : + XcfaLabel(metadata = metadata) { - override fun toString(): String { - return "join $pidVar" - } + override fun toString(): String { + return "join $pidVar" + } - companion object { + companion object { - fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { - val (pidVarName, pidVarType) = Regex("join \\(var (.*) (.*)\\)").matchEntire( - s)!!.destructured - val pidVar = env.eval(scope.resolve(pidVarName).orElseThrow()) as VarDecl<*> - return JoinLabel(pidVar, metadata = metadata) - } + fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { + val (pidVarName, pidVarType) = + Regex("^join \\(var (.*) (.*)\\)$").matchEntire(s)!!.destructured + val pidVar = env.eval(scope.resolve(pidVarName).orElseThrow()) as VarDecl<*> + return JoinLabel(pidVar, metadata = metadata) } + } } enum class ChoiceType { - NONE, - MAIN_PATH, - ALTERNATIVE_PATH + NONE, + MAIN_PATH, + ALTERNATIVE_PATH, } -data class StmtLabel @JvmOverloads constructor( - val stmt: Stmt, - val choiceType: ChoiceType = ChoiceType.NONE, - override val metadata: MetaData = EmptyMetaData +data class StmtLabel +@JvmOverloads +constructor( + val stmt: Stmt, + val choiceType: ChoiceType = ChoiceType.NONE, + override val metadata: MetaData = EmptyMetaData, ) : XcfaLabel(metadata = metadata) { - init { - check( - stmt !is NonDetStmt && stmt !is SequenceStmt) { "NonDetStmt and SequenceStmt are not supported in XCFA. Use the corresponding labels instead." } - } - - override fun toStmt(): Stmt = stmt - override fun toString(): String { - if (choiceType != ChoiceType.NONE) - return "($stmt)[choiceType=$choiceType]" - else - return stmt.toString() + init { + check(stmt !is NonDetStmt && stmt !is SequenceStmt) { + "NonDetStmt and SequenceStmt are not supported in XCFA. Use the corresponding labels instead." } - - companion object { - - fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { - val matchResult = Regex("\\((.*)\\)\\[choiceType=(.*)]").matchEntire(s) - if (matchResult != null) { - val (stmt, choiceTypeStr) = matchResult.destructured - return StmtLabel(StatementWrapper(stmt, scope).instantiate(env), - choiceType = ChoiceType.valueOf(choiceTypeStr), metadata = metadata) - } else { - return StmtLabel(StatementWrapper(s, scope).instantiate(env), - choiceType = ChoiceType.NONE, metadata = metadata) - } - } + } + + override fun toStmt(): Stmt = stmt + + override fun toString(): String { + if (choiceType != ChoiceType.NONE) return "($stmt)[choiceType=$choiceType]" + else return stmt.toString() + } + + companion object { + + fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { + val matchResult = Regex("^\\((.*)\\)\\[choiceType=(.*)]$").matchEntire(s) + if (matchResult != null) { + val (stmt, choiceTypeStr) = matchResult.destructured + return StmtLabel( + StatementWrapper(stmt, scope).instantiate(env), + choiceType = ChoiceType.valueOf(choiceTypeStr), + metadata = metadata, + ) + } else { + return StmtLabel( + StatementWrapper(s, scope).instantiate(env), + choiceType = ChoiceType.NONE, + metadata = metadata, + ) + } } + } } data class ReadLabel( - val local: VarDecl<*>, - val global: VarDecl<*>, - val labels: Set, - override val metadata: MetaData + val local: VarDecl<*>, + val global: VarDecl<*>, + val labels: Set, + override val metadata: MetaData, ) : XcfaLabel(metadata = metadata) { - override fun toString(): String { - return "R[$local <- $global] @$labels" - } + override fun toString(): String { + return "R[$local <- $global] @$labels" + } } -data class WriteLabel constructor( - val local: VarDecl<*>, - val global: VarDecl<*>, - val labels: Set, - override val metadata: MetaData +data class WriteLabel +constructor( + val local: VarDecl<*>, + val global: VarDecl<*>, + val labels: Set, + override val metadata: MetaData, ) : XcfaLabel(metadata = metadata) { - override fun toString(): String { - return "W[$global <- $local] @$labels" - } + override fun toString(): String { + return "W[$global <- $local] @$labels" + } } -data class FenceLabel( - val labels: Set, - override val metadata: MetaData = EmptyMetaData -) : XcfaLabel(metadata = metadata) { +data class FenceLabel(val labels: Set, override val metadata: MetaData = EmptyMetaData) : + XcfaLabel(metadata = metadata) { - override fun toString(): String { - return "F[${labels.joinToString(";")}]" - } + override fun toString(): String { + return "F[${labels.joinToString(";")}]" + } - companion object { + companion object { - fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { - val (labelList) = Regex("F\\[(.*)]").matchEntire(s)!!.destructured - return FenceLabel(labelList.split(";").toSet(), metadata = metadata) - } + fun fromString(s: String, scope: Scope, env: Env, metadata: MetaData): XcfaLabel { + val (labelList) = Regex("^F\\[(.*)]$").matchEntire(s)!!.destructured + return FenceLabel(labelList.split(";").toSet(), metadata = metadata) } + } } -data class SequenceLabel @JvmOverloads constructor( - val labels: List, - override val metadata: MetaData = EmptyMetaData -) : XcfaLabel(metadata = metadata) { +data class SequenceLabel +@JvmOverloads +constructor(val labels: List, override val metadata: MetaData = EmptyMetaData) : + XcfaLabel(metadata = metadata) { - override fun toStmt(): Stmt { - return SequenceStmt(labels.map { it.toStmt() }) - } + override fun toStmt(): Stmt { + return SequenceStmt(labels.map { it.toStmt() }) + } - override fun toString(): String { - val sj = StringJoiner(",", "[", "]") - labels.forEach { sj.add(it.toString()) } - return sj.toString() - } + override fun toString(): String { + val sj = StringJoiner(",", "[", "]") + labels.forEach { sj.add(it.toString()) } + return sj.toString() + } } -data class NondetLabel @JvmOverloads constructor( - val labels: Set, - override val metadata: MetaData = EmptyMetaData -) : XcfaLabel(metadata = metadata) { +data class NondetLabel +@JvmOverloads +constructor(val labels: Set, override val metadata: MetaData = EmptyMetaData) : + XcfaLabel(metadata = metadata) { - override fun toStmt(): Stmt { - return NonDetStmt(labels.map { it.toStmt() }) - } + override fun toStmt(): Stmt { + return NonDetStmt(labels.map { it.toStmt() }) + } - override fun toString(): String { - return "NonDet($labels)" - } + override fun toString(): String { + return "NonDet($labels)" + } } object NopLabel : XcfaLabel(metadata = EmptyMetaData) { - override fun toStmt(): Stmt { - return Skip() - } + override fun toStmt(): Stmt { + return Skip() + } - override fun toString(): String { - return "Nop" - } + override fun toString(): String { + return "Nop" + } } fun getTempLookup(label: XcfaLabel): Map, VarDecl<*>> { - return when (label) { - is InvokeLabel -> { - label.tempLookup - } - - is StartLabel -> { - label.tempLookup - } - - is SequenceLabel -> { - val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() - for (sublabel in label.labels) { - lookup.putAll(getTempLookup(sublabel)) - } - lookup - } - - is NondetLabel -> { - val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() - for (sublabel in label.labels) { - lookup.putAll(getTempLookup(sublabel)) - } - lookup - } - - else -> emptyMap() + return when (label) { + is InvokeLabel -> { + label.tempLookup } -} \ No newline at end of file + + is StartLabel -> { + label.tempLookup + } + + is SequenceLabel -> { + val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() + for (sublabel in label.labels) { + lookup.putAll(getTempLookup(sublabel)) + } + lookup + } + + is NondetLabel -> { + val lookup: MutableMap, VarDecl<*>> = LinkedHashMap() + for (sublabel in label.labels) { + lookup.putAll(getTempLookup(sublabel)) + } + lookup + } + + else -> emptyMap() + } +} diff --git a/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt b/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt index 161f8a4f1a..23235c44a1 100644 --- a/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt +++ b/subprojects/xcfa/xcfa/src/test/java/hu/bme/mit/theta/xcfa/gson/GsonTest.kt @@ -106,6 +106,34 @@ class GsonTest { assertEquals(xcfaSource, output) } + @Test + fun testAsyncRoundtrip() { + val xcfaSource = + xcfa("example") { + global { + "x" type Int() init "0" + "thr1" type Int() init "0" + } + procedure("main") { (init to final) { "thr1".start("proc1", "(mod x 0)") } } + procedure("proc1") { (init to final) { assume("true") } } + } + + val symbolTable = XcfaScope(SymbolTable()) + val x_symbol = NamedSymbol("x") + val thr1_symbol = NamedSymbol("thr1") + symbolTable.add(x_symbol) + symbolTable.add(thr1_symbol) + val env = Env() + env.define(x_symbol, xcfaSource.vars.find { it.wrappedVar.name == "x" }!!.wrappedVar) + env.define(thr1_symbol, xcfaSource.vars.find { it.wrappedVar.name == "thr1" }!!.wrappedVar) + val gson = getGson(symbolTable, env, true) + + val output = gson.fromJson(gson.toJson(xcfaSource), XCFA::class.java) + println(xcfaSource) + println(output) + assertEquals(xcfaSource, output) + } + @Test fun testParseContextRoundTrip() { val parseContext = ParseContext()